toml-parser-0.1.0.0: src/TOML/Parser.y
{
{-# LANGUAGE Trustworthy #-}
{-|
Module : TOML.Parser
Description : /Internal:/ Parser for TOML generated by Happy
Copyright : (c) Eric Mertens, 2017
License : ISC
Maintainer : emertens@gmail.com
Parser for TOML generated by Happy.
-}
module TOML.Parser (parseComponents) where
import Data.Text (Text,pack)
import TOML.Components
import TOML.Errors
import TOML.Located
import TOML.Tokens
import TOML.Value
}
%tokentype { Located Token }
%token
STRING { Located _ (StringToken $$) }
BAREKEY { Located _ (BareKeyToken $$) }
INTEGER { Located _ (IntegerToken $$) }
DOUBLE { Located _ (DoubleToken $$) }
'true' { Located _ TrueToken }
'false' { Located _ FalseToken }
'[' { $$@(Located _ LeftBracketToken)}
']' { Located _ RightBracketToken }
'{' { $$@(Located _ LeftBraceToken) }
'}' { Located _ RightBraceToken }
',' { Located _ CommaToken }
'.' { Located _ PeriodToken }
'=' { Located _ EqualToken }
ZONEDTIME { Located _ (ZonedTimeToken $$) }
LOCALTIME { Located _ (LocalTimeToken $$) }
TIMEOFDAY { Located _ (TimeOfDayToken $$) }
DAY { Located _ (DayToken $$) }
EOF { Located _ EofToken }
%monad { Either TOMLError }
%error { errorP }
-- | Attempt to parse a layout annotated token stream or
-- the token that caused the parse to fail.
%name components
%%
components :: { [Component] }
: componentsR EOF { reverse $1 }
componentsR :: { [Component] }
: keyvalues { [InitialEntry $1] }
| componentsR component keyvalues { $2 $3 : $1 }
component :: { [(Text,Value)] -> Component }
: '[' keys ']' { TableEntry $2 }
| '[' '[' keys ']' ']' { ArrayEntry $3 }
| '[' keys error {% unterminated $1 }
| '[' '[' keys error {% unterminated $2 }
| '[' '[' keys ']' error {% unterminated $1 }
keyvalues :: { [(Text,Value)] }
: keyvaluesR { reverse $1 }
keyvaluesR :: { [(Text,Value)] }
: { [] }
| keyvaluesR key '=' value { ($2,$4):$1 }
keys :: { [Text] }
: keysR { reverse $1 }
keysR :: { [Text] }
: key { [$1] }
| keysR '.' key { $3 : $1 }
key :: { Text }
: BAREKEY { $1 }
| STRING { $1 }
| INTEGER { pack (show $1) }
| 'true' { pack "true" }
| 'false' { pack "false" }
value :: { Value }
: INTEGER { Integer $1 }
| DOUBLE { Double $1 }
| STRING { String $1 }
| ZONEDTIME { ZonedTimeV $1 }
| TIMEOFDAY { TimeOfDayV $1 }
| DAY { DayV $1 }
| LOCALTIME { LocalTimeV $1 }
| 'true' { Bool True }
| 'false' { Bool False }
| '{' inlinetable '}' { Table $2 }
| '[' inlinearray ']' { List $2 }
| '{' inlinetable error {% unterminated $1 }
| '[' inlinearray error {% unterminated $1 }
inlinetable :: { [(Text,Value)] }
: { [] }
| inlinetableR { reverse $1 }
inlinetableR :: { [(Text,Value)] }
: key '=' value { [($1,$3)] }
| inlinetableR ',' key '=' value
{ ($3,$5):$1 }
inlinearray :: { [Value] }
: { [] }
| inlinearrayR { reverse $1 }
| inlinearrayR ',' { reverse $1 }
inlinearrayR :: { [Value] }
: value { [$1] }
| inlinearrayR ',' value { $3 : $1 }
{
-- | This operation is called by happy when no production matches the
-- current token list.
errorP :: [Located Token] {- ^ nonempty remainig tokens -} -> Either TOMLError a
errorP = Left . Unexpected . head
-- | Attempt to parse a layout annotated token stream or
-- the token that caused the parse to fail.
parseComponents ::
[Located Token] {- ^ layout annotated token stream -} ->
Either TOMLError [Component] {- ^ token at failure or result -}
parseComponents = components
-- | Abort the parse with an error indicating that the given token was unmatched.
unterminated :: Located Token -> Either TOMLError a
unterminated = Left . Unterminated
}