1
Fork 0

refactor app parser, from parser

This commit is contained in:
Jake Wheat 2013-12-14 13:05:02 +02:00
parent 3f08adb4c5
commit 65610af74e
2 changed files with 66 additions and 66 deletions

View file

@ -125,18 +125,16 @@ The parsing for the aggregate extensions is here as well:
aggregate([all|distinct] args [order by orderitems]) aggregate([all|distinct] args [order by orderitems])
> aggOrApp :: P ScalarExpr > aggOrApp :: P ScalarExpr
> aggOrApp = do > aggOrApp =
> i <- identifierString > makeApp
> _ <- symbol "(" > <$> identifierString
> d <- try duplicates > <*> parens ((,,) <$> try duplicates
> es <- choice [(:[]) <$> try star > <*> choice [(:[]) <$> try star
> ,commaSep scalarExpr'] > ,commaSep scalarExpr']
> od <- try $ optionMaybe orderBy > <*> try (optionMaybe orderBy))
> _ <- symbol ")" > where
> case (d,od) of > makeApp i (Nothing,es,Nothing) = App i es
> (Nothing,Nothing) -> > makeApp i (d,es,od) = AggregateApp i d es (fromMaybe [] od)
> return $ App i es
> _ -> return $ AggregateApp i d es (fromMaybe [] od)
> duplicates :: P (Maybe Duplicates) > duplicates :: P (Maybe Duplicates)
> duplicates = optionMaybe $ try $ > duplicates = optionMaybe $ try $
@ -161,8 +159,7 @@ always used with the optionSuffix combinator.
> <*> option [] orderBy) > <*> option [] orderBy)
> where > where
> partitionBy = try (keyword_ "partition") >> > partitionBy = try (keyword_ "partition") >>
> keyword_ "by" >> > keyword_ "by" >> commaSep1 scalarExpr'
> commaSep1 scalarExpr'
> windowSuffix _ = fail "" > windowSuffix _ = fail ""
> app :: P ScalarExpr > app :: P ScalarExpr
@ -473,60 +470,48 @@ optional or use try itself. The caller could do this.
== from == from
this parser should be refactored, it is very unclear. Here is the Here is the rough grammar for joins
rough grammar
tref tref
(cross | [natural] (cross | [natural] ([inner] | (left | right | full) [outer])) join
([inner] tref
| left [outer]
| right [outer]
| full [outer]
)
join tref
[on expr | using (...)] [on expr | using (...)]
> from :: P [TableRef] > from :: P [TableRef]
> from = try (keyword_ "from") *> commaSep1 tref > from = try (keyword_ "from") *> commaSep1 tref
> where > where
> tref = choice [try (JoinQueryExpr <$> parens queryExpr) > tref = nonJoinTref >>= optionSuffix joinTrefSuffix
> nonJoinTref = choice [try (JoinQueryExpr <$> parens queryExpr)
> ,JoinParens <$> parens tref > ,JoinParens <$> parens tref
> ,SimpleTableRef <$> identifierString] > ,SimpleTableRef <$> identifierString]
> >>= optionSuffix pjoin > >>= optionSuffix aliasSuffix
> >>= optionSuffix alias > aliasSuffix j =
> pjoin tref0 = > let tableAlias = optional (try $ keyword_ "as") *> identifierString
> choice > columnAliases = optionMaybe $ try $ parens
> [try (keyword_ "natural") *> keyword_ "inner" > $ commaSep1 identifierString
> *> conditionlessSuffix tref0 Inner (Just JoinNatural) > in option j (JoinAlias j <$> try tableAlias <*> try columnAliases)
> ,try (keyword_ "join") > joinTrefSuffix t = (do
> *> (JoinTableRef Inner tref0 <$> tref <*> joinExpr) > nat <- option False $ try (True <$ (try $ keyword_ "natural"))
> ,try (keyword_ "inner") > JoinTableRef <$> joinType
> *> conditionSuffix tref0 Inner > <*> return t
> ,try (choice [JLeft <$ keyword_ "left" > <*> nonJoinTref
> ,JRight <$ keyword_ "right" > <*> optionMaybe (joinCondition nat))
> ,Full <$ keyword_ "full"]) > >>= optionSuffix joinTrefSuffix
> >>= outerJoinSuffix tref0 > joinType = choice
> ,try (keyword_ "cross") > [Cross <$ try (keyword_ "cross")
> *> conditionlessSuffix tref0 Cross Nothing > ,Inner <$ try (keyword_ "inner")
> ,choice [JLeft <$ try (keyword_ "left")
> ,JRight <$ try (keyword_ "right")
> ,Full <$ try (keyword_ "full")]
> <* optional (try $ keyword_ "outer")]
> <* keyword "join"
> joinCondition nat =
> choice [guard nat >> return JoinNatural
> ,try (keyword_ "on") >>
> JoinOn <$> scalarExpr
> ,try (keyword_ "using") >>
> JoinUsing <$> parens (commaSep1 identifierString)
> ] > ]
> >>= optionSuffix pjoin
> outerJoinSuffix tref0 jt =
> optional (keyword_ "outer") *> conditionSuffix tref0 jt
> conditionSuffix tref0 jt =
> keyword_ "join" *> (JoinTableRef jt tref0 <$> tref <*> joinExpr)
> conditionlessSuffix tref0 jt jc =
> keyword_ "join" *> (JoinTableRef jt tref0 <$> tref <*> return jc)
> joinExpr = choice
> [(Just . JoinUsing)
> <$> (try (keyword_ "using")
> *> parens (commaSep1 identifierString))
> ,(Just . JoinOn) <$> (try (keyword_ "on") *> scalarExpr)
> ,return Nothing
> ]
> alias j = let a1 = optional (try (keyword_ "as")) *> identifierString
> a2 = optionMaybe (try $ parens (commaSep1 identifierString))
> in option j (JoinAlias j <$> try a1 <*> try a2)
== simple other parts == simple other parts
@ -666,10 +651,12 @@ blacklist of keywords which aren't supported as identifiers.
> letterDigitOrUnderscore = char '_' <|> alphaNum > letterDigitOrUnderscore = char '_' <|> alphaNum
> blacklist :: [String] > blacklist :: [String]
> blacklist = ["as", "from", "where", "having", "group", "order" > blacklist =
> ["select", "as", "from", "where", "having", "group", "order"
> ,"limit", "offset"
> ,"inner", "left", "right", "full", "natural", "join" > ,"inner", "left", "right", "full", "natural", "join"
> ,"on", "using", "when", "then", "case", "end", "order" > ,"cross", "on", "using"
> ,"limit", "offset", "in" > ,"when", "then", "case", "end", "in"
> ,"except", "intersect", "union"] > ,"except", "intersect", "union"]
TODO: talk about what must be in the blacklist, and what doesn't need TODO: talk about what must be in the blacklist, and what doesn't need
@ -738,6 +725,11 @@ whitespace parser which skips comments also
= generic parser helpers = generic parser helpers
a possible issue with the option suffix is that it enforces left
associativity when chaining it recursively. Have to review
all these uses and figure out if any should be right associative
instead, and create an alternative suffix parser
> optionSuffix :: (a -> P a) -> a -> P a > optionSuffix :: (a -> P a) -> a -> P a
> optionSuffix p a = option a (p a) > optionSuffix p a = option a (p a)

View file

@ -299,6 +299,14 @@
> ,("select a from (t cross join u) as u" > ,("select a from (t cross join u) as u"
> ,ms [JoinAlias (JoinParens $ JoinTableRef Cross (SimpleTableRef "t") > ,ms [JoinAlias (JoinParens $ JoinTableRef Cross (SimpleTableRef "t")
> (SimpleTableRef "u") Nothing) "u" Nothing]) > (SimpleTableRef "u") Nothing) "u" Nothing])
> -- todo: not sure if the associativity is correct
> ,("select a from t cross join u cross join v",
> ms [JoinTableRef Cross
> (JoinTableRef Cross (SimpleTableRef "t")
> (SimpleTableRef "u")
> Nothing)
> (SimpleTableRef "v")
> Nothing])
> ] > ]
> where > where
> ms f = makeSelect {qeSelectList = [(Nothing,Iden "a")] > ms f = makeSelect {qeSelectList = [(Nothing,Iden "a")]