{ {-# LANGUAGE Trustworthy #-} module Config.Parser (parseValue) where import Config.Value (Section(..), Value(..), Atom(..)) import Config.ParserUtils (Parser, runParser, lexerP, errorP) import Config.Tokens (Located(..), Token) import qualified Config.Tokens as T } %tokentype { Located Token } %token SECTION { Located _ (T.Section $$) } STRING { Located _ (T.String $$) } ATOM { Located _ (T.Atom $$) } NUMBER { Located _ $$@T.Number{} } '*' { Located _ T.Bullet } '[' { Located _ T.OpenList } ',' { Located _ T.Comma } ']' { Located _ T.CloseList } '{' { Located _ T.OpenMap } '}' { Located _ T.CloseMap } SEP { Located _ T.LayoutSep } END { Located _ T.LayoutEnd } %monad { Parser (Located Token) } %lexer { (>>=) lexerP } { Located _ T.EOF } %error { errorP } %name value %% value :: { Value } : sections { Sections $1 } | list { List $1 } | simple { $1 } simple :: { Value } : NUMBER { number $1 } | STRING { Text $1 } | ATOM { Atom (MkAtom $1) } | '{' '}' { Sections [] } | '[' inlinelist ']' { List $2 } sections :: { [Section] } : section END { [$1] } | section SEP sections { $1 : $3 } section :: { Section } : SECTION value { Section $1 $2 } list :: { [Value] } : '*' value END { [$2] } | '*' value SEP list { $2 : $4 } inlinelist :: { [Value] } : { [] } | inlinelist1 { $1 } inlinelist1 :: { [Value] } : simple { [$1] } | simple ',' inlinelist1 { $1 : $3 } { -- | Convert number token to number value. This needs a custom -- function like this because there are two value matched from -- the constructor. number :: Token -> Value number = \(T.Number base val) -> Number base val -- | Attempt to parse a layout annotated token stream or -- the token that caused the parse to fail. parseValue :: [Located Token] {- ^ layout annotated token stream -} -> Either (Located Token) Value {- ^ token at failure or result -} parseValue = runParser value }