Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit c21bfa0

Browse files
committed
More cleanup, use constructors where available
1 parent d8df062 commit c21bfa0

File tree

1 file changed

+69
-77
lines changed

1 file changed

+69
-77
lines changed

src/SqlSquared/Parser.purs

Lines changed: 69 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ module SqlSquared.Parser
88
import Prelude
99

1010
import Control.Alt ((<|>))
11+
import Control.Lazy (defer)
1112
import Control.Monad.Error.Class (catchError)
1213
import Control.Monad.State (get, put)
14+
import Control.MonadZero (guard)
1315

1416
import Data.Array as A
1517
import Data.NonEmpty ((:|))
@@ -23,13 +25,15 @@ import Data.Tuple (Tuple(..), uncurry)
2325
import Data.Path.Pathy as Pt
2426
import Data.String as S
2527

26-
import SqlSquared.Utils ((∘), type (×), (×))
28+
import SqlSquared.Constructors as C
2729
import SqlSquared.Parser.Tokenizer (Token(..), TokenStream, PositionedToken, tokenize, Literal(..), printToken)
2830
import SqlSquared.Signature as Sig
31+
import SqlSquared.Utils ((∘), type (×), (×))
2932
import Matryoshka (class Corecursive, embed)
3033

3134
import Text.Parsing.Parser as P
3235
import Text.Parsing.Parser.Combinators as PC
36+
import Text.Parsing.Parser.Pos as PP
3337

3438
type 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 →
5155
asErrorMessage err = flip (<|>) do
5256
P.ParseState input _ _ ← get
5357
case A.head input of
54-
NothingP.fail $ "Expected " <> err <> ", got EOF"
58+
NothingP.fail $ "Expected " <> err <> ", got end of input"
5559
Just tk → P.failWithPosition ("Expected " <> err <> ", got " <> printToken tk.token) tk.position
5660

5761
withToken m a. Monad m String (Token P.ParserT TokenStream m a) P.ParserT TokenStream m a
5862
withToken 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

6367
parse
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

8281
parseModule
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

9198
token m. Monad m P.ParserT TokenStream m Token
9299
token = do
93100
P.ParseState input _ _ ← get
94101
case A.uncons input of
95-
NothingP.fail "Unexpected EOF"
102+
NothingP.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

139146
expr m t. SqlParser' m t
140-
expr = letExpr <|> queryExpr
147+
expr = asErrorMessage "let binding or expression" do
148+
letExpr <|> queryExpr
141149

142150
letExpr m t. SqlParser' m t
143151
letExpr = 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

150158
queryExpr m t. SqlParser' m t
151159
queryExpr = 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

276272
wildcard m t. SqlParser' m t
277273
wildcard = 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

310304
cases m t. SqlParser m t (L.List (Sig.Case t) × Maybe t)
311305
cases = 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

345339
parenList m t. SqlParser m t (L.List t)
346340
parenList = do
@@ -353,7 +347,7 @@ unaryOperator ∷ ∀ m t. SqlParser' m t
353347
unaryOperator = 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
367361
functionExpr = PC.try do
368362
name ← ident
369363
args ← parenList
370-
pure $ embed $ Sig.InvokeFunction { name, args }
364+
pure $ C.invokeFunction name args
371365

372366
functionDecl
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

397391
variable 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

403403
literal m t. SqlParser' m t
404404
literal = PC.tryRethrow $ token >>= case _ of
@@ -421,13 +421,14 @@ arrayLiteral = do
421421
mapLiteral m t. SqlParser' m t
422422
mapLiteral = 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

452453
inSuffix m t. SqlParser m t (t t)
453454
inSuffix = 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

458459
likeSuffix m t. SqlParser m t (t t)
459460
likeSuffix = 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

467468
relationalSuffix m t. SqlParser m t (t t)
468469
relationalSuffix = 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

473474
relationalOp m. Monad m P.ParserT TokenStream m (Sig.BinaryOperator)
474475
relationalOp = 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

606607
filter 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

Comments
 (0)