1
Fork 0

fix the scalar expression operator parsing, use expression operator parsing for set operations too

This commit is contained in:
Jake Wheat 2024-01-10 09:18:07 +00:00
parent 7a5ad6c206
commit 8cc475240b

View file

@ -1165,38 +1165,37 @@ messages, but both of these are too important.
-}
opTable :: Bool -> [[E.Operator Parser ScalarExpr]]
opTable bExpr = [] {-
opTable bExpr =
[-- parse match and quantified comparisons as postfix ops
-- todo: left factor the quantified comparison with regular
-- binary comparison, somehow
[E.Postfix $ try quantifiedComparisonSuffix
,E.Postfix matchPredicateSuffix
]
,E.Postfix matchPredicateSuffix]
,[binarySym "." E.AssocLeft]
,[binarySymL "."]
,[postfix' arraySuffix
,postfix' collateSuffix]
,[E.Postfix arraySuffix
,E.Postfix collateSuffix]
,[prefixSym "+", prefixSym "-"]
,[binarySym "^" E.AssocLeft]
,[binarySymL "^"]
,[binarySym "*" E.AssocLeft
,binarySym "/" E.AssocLeft
,binarySym "%" E.AssocLeft]
,[binarySymL "*"
,binarySymL "/"
,binarySymL "%"]
,[binarySym "+" E.AssocLeft
,binarySym "-" E.AssocLeft]
,[binarySymL "+"
,binarySymL "-"]
,[binarySym "||" E.AssocRight
,[binarySymR "||"
,prefixSym "~"
,binarySym "&" E.AssocRight
,binarySym "|" E.AssocRight]
,binarySymR "&"
,binarySymR "|"]
,[binaryKeyword "overlaps" E.AssocNone]
,[binaryKeywordN "overlaps"]
,[binaryKeyword "like" E.AssocNone
,[binaryKeywordN "like"
-- have to use try with inSuffix because of a conflict
-- with 'in' in position function, and not between
-- between also has a try in it to deal with 'not'
@ -1204,19 +1203,19 @@ opTable bExpr = [] {-
,E.Postfix $ try inSuffix
,E.Postfix betweenSuffix]
-- todo: figure out where to put the try?
++ [binaryKeywords $ makeKeywordTree
++ [binaryKeywordsN $ makeKeywordTree
["not like"
,"is similar to"
,"is not similar to"]]
++ [multisetBinOp]
,[binarySym "<" E.AssocNone
,binarySym ">" E.AssocNone
,binarySym ">=" E.AssocNone
,binarySym "<=" E.AssocNone
,binarySym "!=" E.AssocRight
,binarySym "<>" E.AssocRight
,binarySym "=" E.AssocRight]
,[binarySymN "<"
,binarySymN ">"
,binarySymN ">="
,binarySymN "<="
,binarySymR "!="
,binarySymR "<>"
,binarySymR "="]
,[postfixKeywords $ makeKeywordTree
["is null"
@ -1227,42 +1226,44 @@ opTable bExpr = [] {-
,"is not false"
,"is unknown"
,"is not unknown"]]
++ [binaryKeywords $ makeKeywordTree
++ [binaryKeywordsN $ makeKeywordTree
["is distinct from"
,"is not distinct from"]]
,[prefixKeyword "not"]
,if bExpr then [] else [binaryKeyword "and" E.AssocLeft]
,if bExpr then [] else [binaryKeywordL "and"]
,[binaryKeyword "or" E.AssocLeft]
,[binaryKeywordL "or"]
]
where
binarySym nm assoc = binary (symbol_ nm) nm assoc
binaryKeyword nm assoc = binary (keyword_ nm) nm assoc
binaryKeywords p =
E.Infix (do
binarySymL name = E.InfixL (mkBinOp name <$ symbol_ name)
binarySymR name = E.InfixR (mkBinOp name <$ symbol_ name)
binarySymN name = E.InfixN (mkBinOp name <$ symbol_ name)
binaryKeywordN name = E.InfixN (mkBinOp name <$ keyword_ name)
binaryKeywordL name = E.InfixL (mkBinOp name <$ keyword_ name)
mkBinOp nm a b = BinOp a (mkName nm) b
prefixSym name = E.Prefix (PrefixOp (mkName name) <$ symbol_ name)
prefixKeyword name = E.Prefix (PrefixOp (mkName name) <$ keyword_ name)
mkName nm = [Name Nothing nm]
binaryKeywordsN p =
E.InfixN (do
o <- try p
pure (\a b -> BinOp a [Name Nothing $ unwords o] b))
E.AssocNone
postfixKeywords p =
postfix' $ do
o <- try p
pure $ PostfixOp [Name Nothing $ unwords o]
binary p nm assoc =
E.Infix (p >> pure (\a b -> BinOp a [Name Nothing nm] b)) assoc
multisetBinOp = E.Infix (do
pure (\a b -> BinOp a [Name Nothing $ T.unwords o] b))
multisetBinOp = E.InfixL (do
keyword_ "multiset"
o <- choice [Union <$ keyword_ "union"
,Intersect <$ keyword_ "intersect"
,Except <$ keyword_ "except"]
d <- option SQDefault duplicates
pure (\a b -> MultisetBinOp a o d b))
E.AssocLeft
prefixKeyword nm = prefix (keyword_ nm) nm
prefixSym nm = prefix (symbol_ nm) nm
prefix p nm = prefix' (p >> pure (PrefixOp [Name Nothing nm]))
postfixKeywords p =
E.Postfix $ do
o <- try p
pure $ PostfixOp [Name Nothing $ T.unwords o]
{-
-- hack from here
-- http://stackoverflow.com/questions/10475337/parsec-expr-repeated-prefix-postfix-operator-not-supported
-- not implemented properly yet
@ -1524,10 +1525,10 @@ and union, etc..
-}
queryExpr :: Parser QueryExpr
queryExpr = select {-choice
[with
,undefined {-chainr1-} (choice [values,table, select]) setOp]-}
queryExpr = E.makeExprParser qeterm qeOpTable
where
qeterm = with <|> select <|> table <|> values
select = keyword_ "select" >>
mkSelect
<$> option SQDefault duplicates
@ -1541,6 +1542,19 @@ queryExpr = select {-choice
>> Values <$> commaSep (parens (commaSep scalarExpr))
table = keyword_ "table" >> Table <$> names
qeOpTable =
[[E.InfixL $ setOp Intersect "intersect"]
,[E.InfixL $ setOp Except "except"
,E.InfixL $ setOp Union "union"]]
setOp :: SetOperatorName -> Text -> Parser (QueryExpr -> QueryExpr -> QueryExpr)
setOp ctor opName = cq
<$> (ctor <$ keyword_ opName)
<*> option SQDefault duplicates
<*> corr
cq o d c q0 q1 = QueryExprSetOp q0 o d c q1
corr = option Respectively (Corresponding <$ keyword_ "corresponding")
{-
local data type to help with parsing the bit after the select list,
called 'table expression' in the ansi sql grammar. Maybe this should
@ -1568,20 +1582,6 @@ tableExpression = mkTe <$> from
mkTe f w g h od (ofs,fe) =
TableExpression f w g h od ofs fe
setOp :: Parser (QueryExpr -> QueryExpr -> QueryExpr)
setOp = cq
<$> setOpK
<*> option SQDefault duplicates
<*> corr
where
cq o d c q0 q1 = QueryExprSetOp q0 o d c q1
setOpK = choice [Union <$ keyword_ "union"
,Intersect <$ keyword_ "intersect"
,Except <$ keyword_ "except"]
<?> "set operator"
corr = option Respectively (Corresponding <$ keyword_ "corresponding")
{-
wrapper for query expr which ignores optional trailing semicolon.