packages feed

config-value-0.6: src/Config/Parser.y

{
{-# LANGUAGE Trustworthy #-}

module Config.Parser (parseValue) where

import Config.Value   (Section(..), Value(..), Atom(..))
import Config.Tokens  (Located(..), Token, Position)
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{}          }
FLOATING                        { Located _ T.Floating{}        }
'*'                             { 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         }
EOF                             { Located _ T.EOF               }

%monad { Either (Located Token) }
%error { errorP }

%name config

%%

config ::                       { Value Position                }
  : value EOF                   { $1                            }

value ::                        { Value Position                }
  : sections END                { sections $1                   }
  | '*' list END                { List $1 (reverse $2)          }
  | simple                      { $1                            }

simple ::                       { Value Position                }
  : NUMBER                      { number   $1                   }
  | FLOATING                    { floating $1                   }
  | STRING                      { text     $1                   }
  | ATOM                        { atom     $1                   }
  | '{' inlinesections '}'      { Sections $1 (reverse $2) }
  | '[' inlinelist ']'          { List     $1 (reverse $2) }

sections ::                     { [Section Position]            }
  :              section        { [$1]                          }
  | sections SEP section        { $3 : $1                       }

inlinesections ::               { [Section Position]            }
  :                             { []                            }
  | inlinesections1             { $1                            }
  | inlinesections1 ','         { $1                            }

inlinesections1 ::              { [Section Position]            }
  :                     section { [$1]                          }
  | inlinesections1 ',' section { $3 : $1                       }

section ::                      { Section Position              }
  : SECTION value               { section $1 $2                 }

list ::                         { [Value Position]              }
  :              value          { [$1]                          }
  | list SEP '*' value          { $4 : $1                       }

inlinelist ::                   { [Value Position]              }
  :                             { []                            }
  | inlinelist1                 { $1                            }
  | inlinelist1 ','             { $1                            }

inlinelist1 ::                  { [Value Position]              }
  :                 simple      { [$1]                          }
  | inlinelist1 ',' simple      { $3 : $1                       }

{

-- | Convert number token to number value. This needs a custom
-- function like this because there are two value matched from
-- the constructor.
number :: Located Token -> Value Position
number = \(Located a (T.Number base val)) -> Number a base val

-- | Convert floating token to floating value. This needs a custom
-- function like this because there are two value matched from
-- the constructor.
floating :: Located Token -> Value Position
floating = \(Located a (T.Floating coef expo)) -> Floating a coef expo

section :: Located Token -> Value Position -> Section Position
section = \(Located a (T.Section k)) v -> Section a k v

sections :: [Section Position] -> Value Position
sections xxs = Sections (sectionAnn x) (x:xs)
  where x:xs = reverse xxs

text :: Located Token -> Value Position
text = \(Located a (T.String x)) -> Text a x

atom :: Located Token -> Value Position
atom = \(Located a (T.Atom x)) -> Atom a (MkAtom x)

errorP :: [Located Token] -> Either (Located Token) a
errorP xs = Left (head xs)

-- | 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 Position) {- ^ token at failure or result -}
parseValue = config

}