module Test.Parser
( Parser
, expr
) where
import Text.Parsec
import Test.Expr
import Expression.Reorder (Fixity(..), Assoc(..))
type Parser = Parsec String Int
expr :: String -> LExpr
expr s = case runParser pExpr 0 "" s of
Left e -> error $ "parse error" <> show e
Right x -> x
getColumn :: Parser Int
getColumn = pred . sourceColumn . statePos <$> getParserState
nextIndex :: Parser OpIndex
nextIndex = OpIndex <$> (getState <* modifyState succ)
pExpr :: Parser LExpr
pExpr = pBinary <* eof
pBinary :: Parser LExpr
pBinary = do
x <- pPostfix
xs <- many $ do
p1 <- getColumn
a <- AssocLeft <$ char '<' <|> AssocRight <$ char '>' <|> AssocNone <$ char '='
p <- read <$> many1 digit
_ <- char '.'
p2 <- getColumn
spaces
i <- nextIndex
y <- pPostfix
pure (Fixity a p @@ Pos p1 p2, i, y)
pure $ foldl (\acc (op, i, y) -> ExprBinary i op acc y @@ acc <~> y) x xs
pPostfix :: Parser LExpr
pPostfix = do
x <- pPrefix
os <- many $ choice
[ do
p1 <- getColumn
_ <- char '!'
p <- read <$> many1 digit
_ <- char '.'
p2 <- getColumn
spaces
i <- nextIndex
let op = Fixity AssocRight p @@ Pos p1 p2
pure $ \acc -> ExprPostfix i op acc @@ acc <~> op
, do
p1 <- getColumn
i <- nextIndex
_ <- char '@'
_ <- char '{'
spaces
xs <- pBinary `sepBy` (char ',' >> spaces)
_ <- char '}'
p2 <- getColumn
spaces
let op = xs @@ Pos p1 p2
pure $ \acc -> ExprIndex i acc op @@ acc <~> op
]
pure $ foldl (\acc f -> f acc) x os
pPrefix :: Parser LExpr
pPrefix = do
os <- many $ do
p1 <- getColumn
_ <- char '~'
p <- read <$> many1 digit
_ <- char '.'
p2 <- getColumn
spaces
i <- nextIndex
pure (Fixity AssocLeft p @@ Pos p1 p2, i)
x <- pAssoc <|> pGroup <|> pAtom
pure $ foldl (\acc (op, i) -> ExprPrefix i op acc @@ op <~> acc) x (reverse os)
pAssoc :: Parser LExpr
pAssoc = do
_ <- char '('
spaces
x <- pBinary
_ <- char ')'
spaces
pure x
pGroup :: Parser LExpr
pGroup = do
p1 <- getColumn
_ <- char '{'
spaces
x <- pBinary
_ <- char '}'
p2 <- getColumn
spaces
pure $ ExprGroup x @@ Pos p1 p2
pAtom :: Parser LExpr
pAtom = do
p1 <- getColumn
x <- alphaNum
p2 <- getColumn
spaces
pure $ ExprAtom x @@ Pos p1 p2