lamb/parser.hs

89 lines
2.2 KiB
Haskell
Raw Normal View History

2013-10-19 06:22:42 +00:00
module Parser where
import Text.Parsec
import Text.Parsec.String
import Text.Parsec.Expr
import qualified Text.Parsec.Token as T
import Text.Parsec.Language
import AST
languageDef = emptyDef {T.commentStart="{-",
T.commentEnd="-}",
T.commentLine="--",
T.nestedComments=True,
T.identStart = letter <|> char '_',
T.identLetter = alphaNum <|> char '_',
2013-10-19 08:38:25 +00:00
T.reservedNames = ["do", "end"],
2013-10-19 06:22:42 +00:00
T.reservedOpNames = ["+", "*"]}
lexer = T.makeTokenParser languageDef
exprparser = buildExpressionParser ops term <?> "expression"
ops = [ [Infix (reservedOp "*" >> return Mul) AssocLeft ]
, [Infix (reservedOp "+" >> return Add) AssocLeft]
]
identifier = T.identifier lexer -- parses an identifier
reserved = T.reserved lexer -- parses a reserved name
reservedOp = T.reservedOp lexer -- parses an operator
parens = T.parens lexer -- parses surrounding parenthesis
integer = T.integer lexer -- parses an integer
semi = T.semi lexer -- parses a semicolon
whiteSpace = T.whiteSpace lexer -- parses whitespace
symbol = T.symbol lexer
2013-10-19 08:38:25 +00:00
statement = exprparser
2013-10-19 06:22:42 +00:00
block = do
reserved "do"
lst <- seqStmt
reserved "end"
return $ Block lst
pattern = option UnitP $
fmap VarP identifier
<|> fmap IntP integer
patterns = sepBy pattern (symbol ",")
2013-10-19 06:22:42 +00:00
funDef = do
name <- identifier
symbol "("
pats <- patterns
let pats' = if pats == [] then [UnitP] else pats -- at least Unit
symbol ")"
symbol "->"
2013-10-19 06:22:42 +00:00
lst <- exprparser
return $ rewriteFun (FunDef name (pats, lst))
2013-10-19 06:22:42 +00:00
-- curry FunDef to a definition of lambdas
rewriteFun (FunDef name (patterns, body)) =
Def name lam
where
-- curry it
lam = foldr (\pat lam -> Lambda [(pat, [lam])]) body patterns
2013-10-19 06:22:42 +00:00
call = do
name <- identifier
whiteSpace
symbol "("
2013-10-19 08:44:53 +00:00
args <- sepBy exprparser (symbol ",")
let args' = if args == [] then [UnitConst] else args -- at least Unit
symbol ")"
2013-10-19 08:44:53 +00:00
return $ Call name args'
2013-10-19 06:22:42 +00:00
term = try block
2013-10-19 06:22:42 +00:00
<|> try funDef
<|> try call
<|> parens exprparser
<|> fmap Var identifier
<|> fmap IntConst integer
2013-10-19 08:38:25 +00:00
seqStmt = sepBy1 statement semi
2013-10-19 06:22:42 +00:00
program =
many1 $ do
e <- exprparser
2013-10-19 08:44:53 +00:00
symbol "."
2013-10-19 06:22:42 +00:00
return e
parseProgram = parse program "program"