@@ -8,8 +8,10 @@ module SqlSquared.Parser
88import Prelude
99
1010import Control.Alt ((<|>))
11+ import Control.Lazy (defer )
1112import Control.Monad.Error.Class (catchError )
1213import Control.Monad.State (get , put )
14+ import Control.MonadZero (guard )
1315
1416import Data.Array as A
1517import Data.NonEmpty ((:|))
@@ -23,13 +25,15 @@ import Data.Tuple (Tuple(..), uncurry)
2325import Data.Path.Pathy as Pt
2426import Data.String as S
2527
26- import SqlSquared.Utils ((∘), type (×), (×))
28+ import SqlSquared.Constructors as C
2729import SqlSquared.Parser.Tokenizer (Token (..), TokenStream , PositionedToken , tokenize , Literal (..), printToken )
2830import SqlSquared.Signature as Sig
31+ import SqlSquared.Utils ((∘), type (×), (×))
2932import Matryoshka (class Corecursive , embed )
3033
3134import Text.Parsing.Parser as P
3235import Text.Parsing.Parser.Combinators as PC
36+ import Text.Parsing.Parser.Pos as PP
3337
3438type SqlParser m t r =
3539 Corecursive t (Sig.SqlF EJ.EJsonF )
@@ -51,14 +55,14 @@ asErrorMessage ∷ ∀ m a. Monad m ⇒ String → P.ParserT TokenStream m a →
5155asErrorMessage err = flip (<|>) do
5256 P.ParseState input _ _ ← get
5357 case A .head input of
54- Nothing → P .fail $ " Expected " <> err <> " , got EOF "
58+ Nothing → P .fail $ " Expected " <> err <> " , got end of input "
5559 Just tk → P .failWithPosition (" Expected " <> err <> " , got " <> printToken tk.token) tk.position
5660
5761withToken ∷ ∀ m a . Monad m ⇒ String → (Token → P.ParserT TokenStream m a ) → P.ParserT TokenStream m a
5862withToken err k =
5963 PC .try
6064 $ withErrorMessage (append $ err <> " , got " )
61- ((withErrorMessage' (const " EOF " ) token) >>= k)
65+ ((withErrorMessage' (const " end of input " ) token) >>= k)
6266
6367parse
6468 ∷ ∀ t
@@ -72,27 +76,30 @@ parseQuery
7276 . Corecursive t (Sig.SqlF EJ.EJsonF )
7377 ⇒ String
7478 → E.Either P.ParseError (Sig.SqlQueryF t )
75- parseQuery = tokenize >=> flip P .runParser (go <* eof)
76- where
77- go =
78- Sig.Query
79- <$> (PC .sepEndBy (import_ <|> functionDecl expr) $ operator " ;" )
80- <*> expr
79+ parseQuery = tokenize >=> flip P .runParser (queryTop <* eof)
8180
8281parseModule
8382 ∷ ∀ t
8483 . Corecursive t (Sig.SqlF EJ.EJsonF )
8584 ⇒ String
8685 → E.Either P.ParseError (Sig.SqlModuleF t )
87- parseModule = tokenize >=> flip P .runParser (go <* eof)
88- where
89- go = Sig.Module <$> (PC .sepBy (import_ <|> functionDecl expr) $ operator " ;" )
86+ parseModule = tokenize >=> flip P .runParser (moduleTop <* eof)
87+
88+ queryTop ∷ ∀ m t . SqlParser m t (Sig.SqlQueryF t )
89+ queryTop = defer \_ → Sig.Query <$> (PC .sepEndBy decl $ operator " ;" ) <*> expr
90+
91+ moduleTop ∷ ∀ m t . SqlParser m t (Sig.SqlModuleF t )
92+ moduleTop = defer \_ → Sig.Module <$> PC .sepBy decl (operator " ;" )
93+
94+ decl ∷ ∀ m t . SqlParser m t (Sig.SqlDeclF t )
95+ decl = asErrorMessage " import or function declaration" do
96+ import_ <|> functionDecl expr
9097
9198token ∷ ∀ m . Monad m ⇒ P.ParserT TokenStream m Token
9299token = do
93100 P.ParseState input _ _ ← get
94101 case A .uncons input of
95- Nothing → P .fail " Unexpected EOF "
102+ Nothing → P .fail " Unexpected end of input "
96103 Just { head, tail } → do
97104 put $ P.ParseState tail head.position true
98105 pure head.token
@@ -137,15 +144,16 @@ anyKeyword = withToken "keyword" case _ of
137144 tok → P .fail $ printToken tok
138145
139146expr ∷ ∀ m t . SqlParser' m t
140- expr = letExpr <|> queryExpr
147+ expr = asErrorMessage " let binding or expression" do
148+ letExpr <|> queryExpr
141149
142150letExpr ∷ ∀ m t . SqlParser' m t
143151letExpr = do
144152 i ← PC .try (ident <* operator " :=" )
145153 bindTo ← expr
146154 operator " ;"
147155 in_ ← expr
148- pure $ embed $ Sig.Let { ident: i, bindTo, in_ }
156+ pure $ C .let_ i bindTo in_
149157
150158queryExpr ∷ ∀ m t . SqlParser' m t
151159queryExpr = prod (query <|> definedExpr) queryBinop _BINOP
@@ -157,8 +165,8 @@ queryBinop = asErrorMessage "query operator" $ PC.choice
157165 , keyword " sample" $> Sig.Sample
158166 , keyword " union" $> Sig.Union
159167 , keyword " union" *> keyword " all" $> Sig.UnionAll
168+ , PC .try $ keyword " intersect" *> keyword " all" $> Sig.IntersectAll
160169 , keyword " intersect" $> Sig.Intersect
161- , keyword " intersect" *> keyword " all" $> Sig.IntersectAll
162170 , keyword " except" $> Sig.Except
163171 ]
164172
@@ -229,49 +237,37 @@ derefExpr = do
229237 where
230238 modifier = asErrorMessage " dereference operator" $ PC .choice
231239 [ fieldDeref
232- , operator " {*:}" $> _UNOP Sig.FlattenMapKeys
233- , operator " {*}" $> _UNOP Sig.FlattenMapValues
234- , operator " {:*}" $> _UNOP Sig.FlattenMapValues
235- , operator " {_:}" $> _UNOP Sig.ShiftMapKeys
236- , operator " {_}" $> _UNOP Sig.ShiftMapValues
237- , operator " {:_}" $> _UNOP Sig.ShiftMapValues
240+ , operator " {*:}" $> C .unop Sig.FlattenMapKeys
241+ , operator " {*}" $> C .unop Sig.FlattenMapValues
242+ , operator " {:*}" $> C .unop Sig.FlattenMapValues
243+ , operator " {_:}" $> C .unop Sig.ShiftMapKeys
244+ , operator " {_}" $> C .unop Sig.ShiftMapValues
245+ , operator " {:_}" $> C .unop Sig.ShiftMapValues
238246 , fieldDerefExpr
239- , operator " [*:]" $> _UNOP Sig.FlattenArrayIndices
240- , operator " [*]" $> _UNOP Sig.FlattenArrayValues
241- , operator " [:*]" $> _UNOP Sig.FlattenArrayValues
242- , operator " [_:]" $> _UNOP Sig.ShiftArrayIndices
243- , operator " [_]" $> _UNOP Sig.ShiftArrayValues
247+ , operator " [*:]" $> C .unop Sig.FlattenArrayIndices
248+ , operator " [*]" $> C .unop Sig.FlattenArrayValues
249+ , operator " [:*]" $> C .unop Sig.FlattenArrayValues
250+ , operator " [_:]" $> C .unop Sig.ShiftArrayIndices
251+ , operator " [_]" $> C .unop Sig.ShiftArrayValues
244252 , indexDerefExpr
245253 ]
246254
247255 fieldDeref = do
248256 operator " ."
249257 k ← ident
250- pure \e → embed $ Sig.Binop
251- { op: Sig.FieldDeref
252- , lhs: e
253- , rhs: embed $ Sig.Ident k
254- }
258+ pure \e → C .binop Sig.FieldDeref e (C .ident k)
255259
256260 fieldDerefExpr = do
257261 operator " {"
258262 rhs ← expr
259263 operator " }"
260- pure \e → embed $ Sig.Binop
261- { op: Sig.FieldDeref
262- , lhs: e
263- , rhs
264- }
264+ pure \e → C .binop Sig.FieldDeref e rhs
265265
266266 indexDerefExpr = do
267267 operator " ["
268268 rhs ← expr
269269 operator " ]"
270- pure \e → embed $ Sig.Binop
271- { op: Sig.IndexDeref
272- , lhs: e
273- , rhs
274- }
270+ pure \e → C .binop Sig.IndexDeref e rhs
275271
276272wildcard ∷ ∀ m t . SqlParser' m t
277273wildcard = operator " *" $> embed (Sig.Splice Nothing )
@@ -298,14 +294,12 @@ caseExpr = PC.try switchExpr <|> matchExpr
298294 where
299295 switchExpr = do
300296 _ ← keyword " case"
301- cs × else_ ← cases
302- pure $ embed $ Sig.Switch { cases: cs, else_ }
297+ uncurry C .switch <$> cases
303298
304299 matchExpr = do
305300 _ ← keyword " case"
306301 e ← expr
307- cs × else_ ← cases
308- pure $ embed $ Sig.Match { expr: e, cases: cs, else_ }
302+ uncurry (C .match e) <$> cases
309303
310304cases ∷ ∀ m t . SqlParser m t (L.List (Sig.Case t ) × Maybe t )
311305cases = do
@@ -331,7 +325,7 @@ unshiftExpr = unshiftArrayExpr <|> unshiftMapExpr
331325 e ← expr
332326 _ ← operator " ..."
333327 _ ← operator " ]"
334- pure $ embed $ Sig.Unop { op: Sig.UnshiftArray , expr: e }
328+ pure $ C .unop Sig.UnshiftArray e
335329
336330 unshiftMapExpr = do
337331 _ ← operator " {"
@@ -340,7 +334,7 @@ unshiftExpr = unshiftArrayExpr <|> unshiftMapExpr
340334 rhs ← expr
341335 _ ← operator " ..."
342336 _ ← operator " }"
343- pure $ embed $ Sig.Binop { op: Sig.UnshiftMap , lhs, rhs }
337+ pure $ C .binop Sig.UnshiftMap lhs rhs
344338
345339parenList ∷ ∀ m t . SqlParser m t (L.List t )
346340parenList = do
@@ -353,7 +347,7 @@ unaryOperator ∷ ∀ m t. SqlParser' m t
353347unaryOperator = do
354348 op ← unaryOp
355349 e ← primaryExpr
356- pure $ embed $ Sig.Unop { op, expr: e }
350+ pure $ C .unop op e
357351 where
358352 unaryOp = PC .choice
359353 [ operator " -" $> Sig.Negative
@@ -367,7 +361,7 @@ functionExpr ∷ ∀ m t. SqlParser' m t
367361functionExpr = PC .try do
368362 name ← ident
369363 args ← parenList
370- pure $ embed $ Sig.InvokeFunction { name, args }
364+ pure $ C .invokeFunction name args
371365
372366functionDecl
373367 ∷ ∀ m a
@@ -378,7 +372,7 @@ functionDecl parseExpr = asErrorMessage "function declaration" do
378372 _ ← PC .try $ keyword " create" *> keyword " function"
379373 name ← ident
380374 operator " ("
381- args ← PC .sepBy (operator " : " *> (ident <|> anyKeyword)) $ operator " ,"
375+ args ← PC .sepBy variableString $ operator " ,"
382376 operator " )"
383377 _ ← keyword " begin"
384378 body ← parseExpr
@@ -395,10 +389,16 @@ import_ = asErrorMessage "import declaration" do
395389 pure $ Sig.Import s
396390
397391variable ∷ ∀ m t . SqlParser' m t
398- variable = asErrorMessage " variable" do
392+ variable = C .vari <$> variableString
393+
394+ variableString ∷ ∀ m . Monad m ⇒ P.ParserT TokenStream m String
395+ variableString = asErrorMessage " variable" $ PC .try do
399396 operator " :"
397+ PP.Position pos1 ← P .position
400398 s ← ident <|> anyKeyword
401- pure $ embed $ Sig.Vari s
399+ PP.Position pos2 ← P .position
400+ guard (pos1.line == pos2.line && pos2.column == pos1.column + 1 )
401+ pure s
402402
403403literal ∷ ∀ m t . SqlParser' m t
404404literal = PC .tryRethrow $ token >>= case _ of
@@ -421,13 +421,14 @@ arrayLiteral = do
421421mapLiteral ∷ ∀ m t . SqlParser' m t
422422mapLiteral = do
423423 operator " {"
424- els ← PC .sepBy pair $ operator " ,"
424+ els ← PC .sepBy keyValuePair $ operator " ,"
425425 operator " }"
426426 pure $ embed $ Sig.Literal $ EJ.Map $ EJ.EJsonMap $ A .fromFoldable els
427427
428- pair ∷ ∀ m t . SqlParser m t (t × t )
429- pair = do
430- l ← PC .try $ expr <* operator " :"
428+ keyValuePair ∷ ∀ m t . SqlParser m t (t × t )
429+ keyValuePair = do
430+ l ← expr
431+ operator " :"
431432 r ← expr
432433 pure $ l × r
433434
@@ -447,13 +448,13 @@ betweenSuffix = do
447448 lhs ← defaultExpr
448449 _ ← keyword " and"
449450 rhs ← defaultExpr
450- pure $ \e → embed $ Sig.InvokeFunction { name: " BETWEEN" , args: e: lhs: rhs: L.Nil }
451+ pure \e → C .invokeFunction " BETWEEN" (e : lhs : rhs : L.Nil )
451452
452453inSuffix ∷ ∀ m t . SqlParser m t (t → t )
453454inSuffix = do
454455 _ ← keyword " in"
455456 rhs ← defaultExpr
456- pure $ \lhs → embed $ Sig.Binop { op: Sig.In , lhs, rhs }
457+ pure \lhs → C .binop Sig.In lhs rhs
457458
458459likeSuffix ∷ ∀ m t . SqlParser m t (t → t )
459460likeSuffix = do
@@ -462,13 +463,13 @@ likeSuffix = do
462463 mbEsc ← PC .optionMaybe do
463464 _ ← keyword " escape"
464465 defaultExpr
465- pure $ \lhs → _LIKE mbEsc lhs rhs
466+ pure \lhs → _LIKE mbEsc lhs rhs
466467
467468relationalSuffix ∷ ∀ m t . SqlParser m t (t → t )
468469relationalSuffix = do
469470 op ← relationalOp
470471 rhs ← defaultExpr
471- pure $ \lhs → embed $ Sig.Binop { op, lhs, rhs }
472+ pure \lhs → C .binop op lhs rhs
472473
473474relationalOp ∷ ∀ m . Monad m ⇒ P.ParserT TokenStream m (Sig.BinaryOperator )
474475relationalOp = PC .choice
@@ -510,7 +511,7 @@ relations = do
510511 foldFn (Just left) right =
511512 Just $ Sig.JoinRelation
512513 { joinType: Sig.InnerJoin , left, right
513- , clause: embed $ Sig.Literal $ EJ.Boolean true
514+ , clause: C .bool true
514515 }
515516 res = F .foldl foldFn Nothing rels
516517 case res of
@@ -600,7 +601,7 @@ crossJoinRelation = do
600601 { joinType: Sig.InnerJoin
601602 , left
602603 , right
603- , clause: embed $ Sig.Literal $ EJ.Boolean true
604+ , clause: C .bool true
604605 }
605606
606607filter ∷ ∀ m t . SqlParser' m t
@@ -659,25 +660,16 @@ projection = do
659660 pure $ Sig.Projection { expr: e, alias: a }
660661
661662_SEARCH ∷ ∀ t . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ Boolean → t → t → t
662- _SEARCH b lhs rhs = embed $ Sig.InvokeFunction
663- { name: " SEARCH"
664- , args: lhs : rhs : (embed $ Sig.Literal $ EJ.Boolean b) : L.Nil
665- }
663+ _SEARCH b lhs rhs = C .invokeFunction " SEARCH" $ lhs : rhs : (C .bool b) : L.Nil
666664
667665_LIKE ∷ ∀ t . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ Maybe t → t → t → t
668- _LIKE mbEsc lhs rhs = embed $ Sig.InvokeFunction
669- { name: " LIKE"
670- , args: lhs : rhs : (fromMaybe (embed $ Sig.Literal $ EJ.String " \\ " ) mbEsc) : L.Nil
671- }
666+ _LIKE mbEsc lhs rhs = C .invokeFunction " LIKE" $ lhs : rhs : (fromMaybe (C .string " \\ " ) mbEsc) : L.Nil
672667
673668_NOT ∷ ∀ t . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ t → t
674- _NOT e = embed $ Sig.Unop {op: Sig.Not , expr: e}
669+ _NOT = C .unop Sig.Not
675670
676671_BINOP ∷ ∀ t . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ t → Sig.BinaryOperator → t → t
677- _BINOP lhs op rhs = embed $ Sig.Binop { lhs, op, rhs }
672+ _BINOP = flip C .binop
678673
679674_BINOP' ∷ ∀ t a . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ Sig.BinaryOperator → t → a → t → t
680- _BINOP' op lhs _ rhs = embed $ Sig.Binop { lhs, op, rhs }
681-
682- _UNOP ∷ ∀ t . Corecursive t (Sig.SqlF EJ.EJsonF ) ⇒ Sig.UnaryOperator → t → t
683- _UNOP op e = embed $ Sig.Unop { op, expr: e }
675+ _BINOP' op lhs _ = C .binop op lhs
0 commit comments