start reworking some of the combinators
This commit is contained in:
parent
0248bb90b3
commit
9ee2a1beab
|
@ -184,7 +184,7 @@ fixing them in the syntax but leaving them till the semantic checking
|
||||||
|
|
||||||
> import Control.Monad.Identity (Identity)
|
> import Control.Monad.Identity (Identity)
|
||||||
> import Control.Monad (guard, void, when)
|
> import Control.Monad (guard, void, when)
|
||||||
> import Control.Applicative ((<$), (<$>), (<*>) ,(<*), (*>))
|
> import Control.Applicative ((<$), (<$>), (<*>) ,(<*), (*>), (<**>))
|
||||||
> import Data.Maybe (fromMaybe,catMaybes)
|
> import Data.Maybe (fromMaybe,catMaybes)
|
||||||
> import Data.Char (toLower)
|
> import Data.Char (toLower)
|
||||||
> import Text.Parsec (errorPos,sourceLine,sourceColumn,sourceName
|
> import Text.Parsec (errorPos,sourceLine,sourceColumn,sourceName
|
||||||
|
@ -192,7 +192,7 @@ fixing them in the syntax but leaving them till the semantic checking
|
||||||
> ,option,between,sepBy,sepBy1,string,manyTill,anyChar
|
> ,option,between,sepBy,sepBy1,string,manyTill,anyChar
|
||||||
> ,try,string,many1,oneOf,digit,(<|>),choice,char,eof
|
> ,try,string,many1,oneOf,digit,(<|>),choice,char,eof
|
||||||
> ,optionMaybe,optional,many,letter,parse
|
> ,optionMaybe,optional,many,letter,parse
|
||||||
> ,chainl1, (<?>),notFollowedBy,alphaNum, lookAhead)
|
> ,chainl1, chainr1,(<?>),notFollowedBy,alphaNum, lookAhead)
|
||||||
> import Text.Parsec.String (Parser)
|
> import Text.Parsec.String (Parser)
|
||||||
> import qualified Text.Parsec as P (ParseError)
|
> import qualified Text.Parsec as P (ParseError)
|
||||||
> import Text.Parsec.Perm (permute,(<$?>), (<|?>))
|
> import Text.Parsec.Perm (permute,(<$?>), (<|?>))
|
||||||
|
@ -306,11 +306,19 @@ u&"example quoted"
|
||||||
> ,UQName <$> uquotedIdentifier
|
> ,UQName <$> uquotedIdentifier
|
||||||
> ,Name <$> identifierBlacklist blacklist]
|
> ,Name <$> identifierBlacklist blacklist]
|
||||||
|
|
||||||
|
todo: replace (:[]) with a named function all over
|
||||||
|
|
||||||
> names :: Parser [Name]
|
> names :: Parser [Name]
|
||||||
> names = ((:[]) <$> name) >>= optionSuffix another
|
> names = reverse <$> repeatPostfix ((:[]) <$> name) anotherName
|
||||||
|
> -- can't use a simple chain here since we
|
||||||
|
> -- want to wrap the . + name in a try
|
||||||
|
> -- this will change when this is left factored
|
||||||
> where
|
> where
|
||||||
> another n =
|
> anotherName :: Parser ([Name] -> [Name])
|
||||||
> (((n++) . (:[])) <$> try (symbol "." *> name)) >>= optionSuffix another
|
> anotherName = try ((:) <$> (symbol "." *> name))
|
||||||
|
|
||||||
|
> repeatPostfix :: Parser a -> Parser (a -> a) -> Parser a
|
||||||
|
> repeatPostfix p q = foldr ($) <$> p <*> (reverse <$> many q)
|
||||||
|
|
||||||
= Type Names
|
= Type Names
|
||||||
|
|
||||||
|
@ -420,8 +428,9 @@ TODO: this code needs heavy refactoring
|
||||||
|
|
||||||
> typeName :: Parser TypeName
|
> typeName :: Parser TypeName
|
||||||
> typeName =
|
> typeName =
|
||||||
> (rowTypeName <|> intervalTypeName <|> otherTypeName)
|
> repeatPostfix
|
||||||
> >>= tnSuffix
|
> (rowTypeName <|> intervalTypeName <|> otherTypeName)
|
||||||
|
> tnSuffix
|
||||||
> <?> "typename"
|
> <?> "typename"
|
||||||
> where
|
> where
|
||||||
> -- row type names - a little like create table
|
> -- row type names - a little like create table
|
||||||
|
@ -438,6 +447,7 @@ TODO: this code needs heavy refactoring
|
||||||
> otherTypeName = do
|
> otherTypeName = do
|
||||||
> tn <- (try reservedTypeNames <|> names)
|
> tn <- (try reservedTypeNames <|> names)
|
||||||
> choice [try $ timezone tn
|
> choice [try $ timezone tn
|
||||||
|
> -- todo: use the P (a->a) style
|
||||||
> ,try (precscale tn) >>= optionSuffix charSuffix
|
> ,try (precscale tn) >>= optionSuffix charSuffix
|
||||||
> ,try $ lob tn
|
> ,try $ lob tn
|
||||||
> ,optionSuffix charSuffix $ TypeName tn]
|
> ,optionSuffix charSuffix $ TypeName tn]
|
||||||
|
@ -480,14 +490,11 @@ TODO: this code needs heavy refactoring
|
||||||
> lobUnits = choice [PrecCharacters <$ keyword_ "characters"
|
> lobUnits = choice [PrecCharacters <$ keyword_ "characters"
|
||||||
> ,PrecOctets <$ keyword_ "octets"]
|
> ,PrecOctets <$ keyword_ "octets"]
|
||||||
> -- deal with multiset and array suffixes
|
> -- deal with multiset and array suffixes
|
||||||
> tnSuffix x =
|
> tnSuffix :: Parser (TypeName -> TypeName)
|
||||||
> multisetSuffix x <|> arrayTNSuffix x <|> return x
|
> tnSuffix = multisetSuffix <|> arrayTNSuffix
|
||||||
> multisetSuffix x =
|
> multisetSuffix = MultisetTypeName <$ keyword_ "multiset"
|
||||||
> (MultisetTypeName x <$ keyword_ "multiset") >>= tnSuffix
|
> arrayTNSuffix = keyword_ "array" >>
|
||||||
> arrayTNSuffix x =
|
> flip ArrayTypeName <$> optionMaybe (brackets unsignedInteger)
|
||||||
> (keyword_ "array" >> ArrayTypeName x
|
|
||||||
> <$> optionMaybe (brackets unsignedInteger)
|
|
||||||
> ) >>= tnSuffix
|
|
||||||
> -- this parser handles the fixed set of multi word
|
> -- this parser handles the fixed set of multi word
|
||||||
> -- type names, plus all the type names which are
|
> -- type names, plus all the type names which are
|
||||||
> -- reserved words
|
> -- reserved words
|
||||||
|
@ -850,6 +857,9 @@ if there are no value exprs
|
||||||
> makeApp i (SQDefault,es,Nothing) = App i es
|
> makeApp i (SQDefault,es,Nothing) = App i es
|
||||||
> makeApp i (d,es,od) = AggregateApp i d es (fromMaybe [] od) Nothing
|
> makeApp i (d,es,od) = AggregateApp i d es (fromMaybe [] od) Nothing
|
||||||
|
|
||||||
|
TODO: change all these suffix functions to use type
|
||||||
|
Parser (ValueExpr -> ValueExpr)
|
||||||
|
|
||||||
> app :: [Name] -> Parser ValueExpr
|
> app :: [Name] -> Parser ValueExpr
|
||||||
> app n = aggOrApp n >>= \a -> choice
|
> app n = aggOrApp n >>= \a -> choice
|
||||||
> [windowSuffix a
|
> [windowSuffix a
|
||||||
|
@ -940,8 +950,6 @@ in: two variations:
|
||||||
a in (expr0, expr1, ...)
|
a in (expr0, expr1, ...)
|
||||||
a in (queryexpr)
|
a in (queryexpr)
|
||||||
|
|
||||||
this is parsed as a postfix operator which is why it is in this form
|
|
||||||
|
|
||||||
> inSuffix :: Parser (ValueExpr -> ValueExpr)
|
> inSuffix :: Parser (ValueExpr -> ValueExpr)
|
||||||
> inSuffix =
|
> inSuffix =
|
||||||
> mkIn <$> inty
|
> mkIn <$> inty
|
||||||
|
@ -1232,6 +1240,8 @@ tref
|
||||||
> from :: Parser [TableRef]
|
> from :: Parser [TableRef]
|
||||||
> from = keyword_ "from" *> commaSep1 tref
|
> from = keyword_ "from" *> commaSep1 tref
|
||||||
> where
|
> where
|
||||||
|
> -- TODO: use P (a->) for the join tref suffix
|
||||||
|
> -- chainl or buildexpressionparser
|
||||||
> tref = nonJoinTref >>= optionSuffix joinTrefSuffix
|
> tref = nonJoinTref >>= optionSuffix joinTrefSuffix
|
||||||
> nonJoinTref = choice
|
> nonJoinTref = choice
|
||||||
> [parens $ choice
|
> [parens $ choice
|
||||||
|
@ -1243,9 +1253,8 @@ tref
|
||||||
> n <- names
|
> n <- names
|
||||||
> choice [TRFunction n
|
> choice [TRFunction n
|
||||||
> <$> parens (commaSep valueExpr)
|
> <$> parens (commaSep valueExpr)
|
||||||
> ,return $ TRSimple n]]
|
> ,return $ TRSimple n]] <??> aliasSuffix
|
||||||
> >>= optionSuffix aliasSuffix
|
> aliasSuffix = flip TRAlias <$> fromAlias
|
||||||
> aliasSuffix j = option j (TRAlias j <$> fromAlias)
|
|
||||||
> joinTrefSuffix t =
|
> joinTrefSuffix t =
|
||||||
> (TRJoin t <$> option False (True <$ keyword_ "natural")
|
> (TRJoin t <$> option False (True <$ keyword_ "natural")
|
||||||
> <*> joinType
|
> <*> joinType
|
||||||
|
@ -1356,7 +1365,7 @@ and union, etc..
|
||||||
> queryExpr :: Parser QueryExpr
|
> queryExpr :: Parser QueryExpr
|
||||||
> queryExpr = choice
|
> queryExpr = choice
|
||||||
> [with
|
> [with
|
||||||
> ,choice [values,table, select] >>= optionSuffix queryExprSuffix]
|
> ,chainr1 (choice [values,table, select]) setOp]
|
||||||
> where
|
> where
|
||||||
> select = keyword_ "select" >>
|
> select = keyword_ "select" >>
|
||||||
> mkSelect
|
> mkSelect
|
||||||
|
@ -1396,30 +1405,33 @@ be in the public syntax?
|
||||||
> mkTe f w g h od (ofs,fe) =
|
> mkTe f w g h od (ofs,fe) =
|
||||||
> TableExpression f w g h od ofs fe
|
> TableExpression f w g h od ofs fe
|
||||||
|
|
||||||
> queryExprSuffix :: QueryExpr -> Parser QueryExpr
|
> setOp :: Parser (QueryExpr -> QueryExpr -> QueryExpr)
|
||||||
> queryExprSuffix qe = cqSuffix >>= optionSuffix queryExprSuffix
|
> setOp = cq
|
||||||
|
> <$> setOpK
|
||||||
|
> <*> (fromMaybe SQDefault <$> duplicates)
|
||||||
|
> <*> corr
|
||||||
> where
|
> where
|
||||||
> cqSuffix = CombineQueryExpr qe
|
> cq o d c q0 q1 = CombineQueryExpr q0 o d c q1
|
||||||
> <$> setOp
|
> setOpK = choice [Union <$ keyword_ "union"
|
||||||
> <*> (fromMaybe SQDefault <$> duplicates)
|
> ,Intersect <$ keyword_ "intersect"
|
||||||
> <*> corr
|
> ,Except <$ keyword_ "except"]
|
||||||
> <*> queryExpr
|
|
||||||
> setOp = choice [Union <$ keyword_ "union"
|
|
||||||
> ,Intersect <$ keyword_ "intersect"
|
|
||||||
> ,Except <$ keyword_ "except"]
|
|
||||||
> <?> "set operator"
|
> <?> "set operator"
|
||||||
> corr = option Respectively (Corresponding <$ keyword_ "corresponding")
|
> corr = option Respectively (Corresponding <$ keyword_ "corresponding")
|
||||||
|
|
||||||
|
|
||||||
wrapper for query expr which ignores optional trailing semicolon.
|
wrapper for query expr which ignores optional trailing semicolon.
|
||||||
|
|
||||||
|
TODO: change style
|
||||||
|
|
||||||
> topLevelQueryExpr :: Parser QueryExpr
|
> topLevelQueryExpr :: Parser QueryExpr
|
||||||
> topLevelQueryExpr = queryExpr >>= optionSuffix ((semi *>) . return)
|
> topLevelQueryExpr = queryExpr <??> (id <$ semi)
|
||||||
|
|
||||||
wrapper to parse a series of query exprs from a single source. They
|
wrapper to parse a series of query exprs from a single source. They
|
||||||
must be separated by semicolon, but for the last expression, the
|
must be separated by semicolon, but for the last expression, the
|
||||||
trailing semicolon is optional.
|
trailing semicolon is optional.
|
||||||
|
|
||||||
|
TODO: change style
|
||||||
|
|
||||||
> queryExprs :: Parser [QueryExpr]
|
> queryExprs :: Parser [QueryExpr]
|
||||||
> queryExprs = (:[]) <$> queryExpr
|
> queryExprs = (:[]) <$> queryExpr
|
||||||
> >>= optionSuffix ((semi *>) . return)
|
> >>= optionSuffix ((semi *>) . return)
|
||||||
|
@ -1511,24 +1523,15 @@ making a decision on how to represent numbers, the client code can
|
||||||
make this choice.
|
make this choice.
|
||||||
|
|
||||||
> numberLiteral :: Parser String
|
> numberLiteral :: Parser String
|
||||||
> numberLiteral =
|
> numberLiteral = lexeme (
|
||||||
> lexeme (numToken <* notFollowedBy (alphaNum <|> char '.'))
|
> int <??> (pp dot <??.> pp int) <??> pp expon
|
||||||
> <?> "number literal"
|
> <|> (++) <$> dot <*> int <??> pp expon)
|
||||||
> where
|
> where
|
||||||
> numToken = choice [int
|
|
||||||
> >>= optionSuffix dot
|
|
||||||
> >>= optionSuffix fracts
|
|
||||||
> >>= optionSuffix expon
|
|
||||||
> ,fract "" >>= optionSuffix expon]
|
|
||||||
> int = many1 digit
|
> int = many1 digit
|
||||||
> fract p = dot p >>= fracts
|
> dot = string "."
|
||||||
> dot p = (p++) <$> string "."
|
> expon = (:) <$> oneOf "eE" <*> sInt
|
||||||
> fracts p = (p++) <$> int
|
> sInt = (++) <$> option "" (string "+" <|> string "-") <*> int
|
||||||
> expon p = concat <$> sequence
|
> pp = ((++) <$$>)
|
||||||
> [return p
|
|
||||||
> ,(:[]) <$> oneOf "eE"
|
|
||||||
> ,option "" (string "+" <|> string "-")
|
|
||||||
> ,int]
|
|
||||||
|
|
||||||
|
|
||||||
> identifier :: Parser String
|
> identifier :: Parser String
|
||||||
|
@ -1666,6 +1669,9 @@ associativity when chaining it recursively. Have to review
|
||||||
all these uses and figure out if any should be right associative
|
all these uses and figure out if any should be right associative
|
||||||
instead, and create an alternative suffix parser
|
instead, and create an alternative suffix parser
|
||||||
|
|
||||||
|
This is no good, and should be replaced with chain and <??> which has
|
||||||
|
a different type
|
||||||
|
|
||||||
> optionSuffix :: (a -> Parser a) -> a -> Parser a
|
> optionSuffix :: (a -> Parser a) -> a -> Parser a
|
||||||
> optionSuffix p a = option a (p a)
|
> optionSuffix p a = option a (p a)
|
||||||
|
|
||||||
|
@ -2068,3 +2074,26 @@ context
|
||||||
> ++ replicate (sourceColumn p - 1) ' ' ++ "^\n"
|
> ++ replicate (sourceColumn p - 1) ' ' ++ "^\n"
|
||||||
> _ -> ""
|
> _ -> ""
|
||||||
> p = errorPos e
|
> p = errorPos e
|
||||||
|
|
||||||
|
parses an optional postfix element and applies its result to its left
|
||||||
|
hand result, taken from uu-parsinglib
|
||||||
|
|
||||||
|
TODO: make sure the precedence higher than <|> and lower than the
|
||||||
|
other operators so it can be used nicely
|
||||||
|
|
||||||
|
> (<??>) :: Parser a -> Parser (a -> a) -> Parser a
|
||||||
|
> p <??> q = p <**> option id q
|
||||||
|
|
||||||
|
|
||||||
|
this is analogous to <**>
|
||||||
|
|
||||||
|
> (<$$>) :: (a -> b -> c) -> Parser b -> Parser (a -> c)
|
||||||
|
> (<$$>) = (<$>) . flip
|
||||||
|
|
||||||
|
|
||||||
|
composing suffix parsers, not sure about the name
|
||||||
|
|
||||||
|
> (<??.>) :: Parser (a -> a) -> Parser (a -> a) -> Parser (a -> a)
|
||||||
|
> (<??.>) pa pb = (.) <$$> pa <*> option id pb
|
||||||
|
|
||||||
|
|
||||||
|
|
8
TODO
8
TODO
|
@ -5,6 +5,14 @@ continue 2011 review and tests
|
||||||
2. start thinking about automated tests for invalid syntax to catch
|
2. start thinking about automated tests for invalid syntax to catch
|
||||||
bad parsing
|
bad parsing
|
||||||
|
|
||||||
|
|
||||||
|
fixing the non idiomatic (pun!) suffix parsing:
|
||||||
|
typename parsing
|
||||||
|
identifier/app/agg/window parsing
|
||||||
|
join parsing in trefs (use chain? - tricky because of postfix onExpr)
|
||||||
|
top level and queryexprs parsing
|
||||||
|
number literal
|
||||||
|
|
||||||
review names in the syntax for correspondence with sql standard, avoid
|
review names in the syntax for correspondence with sql standard, avoid
|
||||||
gratuitous differences
|
gratuitous differences
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue