3
-- import the the library functions from uulib
7
-- import our custom made Alex-scanner
11
-- Some boilerplate code to use the parser
12
-- Give `parsetokens' your parser and a list of tokens, returned by the `scanTokens'
13
-- function exported by the Scanner module, then you get either a list of error
14
-- messages in case of a parse error, or the parse tree.
15
type TokenParser a = Parser Token a
17
parseTokens :: TokenParser a -> [Token] -> Either [String] a
20
then final `seq` Right v
21
else Left (map show msgs)
25
(Pair v final) = evalSteps steps
28
-- define a parse tree
35
| Let String -- variable
41
-- write a parser for it
42
-- Note: * make sure that the parser is not left recursive
43
-- (to the left is never a pExpr, or always a terminal first)
44
-- * make sure that the parser is not ambiguous
45
-- (by introducing priority levels for the operators)
48
-- Term -> let var = Expr in Expr
49
pExpr :: TokenParser Expr
51
= (\_ x _ e _ b -> Let x e b) <$> pKey "let" <*> pVarid <*> pKey "=" <*> pExpr <*> pKey "in" <*> pExpr
54
-- Expr -> Factor | Factor * Expr
55
pMult :: TokenParser Expr
58
<|> (\l _ r -> Times l r) <$> pFactor <*> pKey "*" <*> pExpr
60
-- Factor -> Term | Term * Factor
61
pFactor :: TokenParser Expr
64
<|> (\l _ r -> Plus l r) <$> pTerm <*> pKey "+" <*> pFactor
70
pTerm :: TokenParser Expr
72
= Identifier <$> pVarid
73
<|> (Integer . read) <$> pInteger16
74
<|> (String . read) <$> pString
75
<|> (\_ e _ -> e) <$> pKey "(" <*> pExpr <*> pKey ")"
81
= let res = parseTokens pExpr (tokenize "nofile" "let x = 3 in x+x")
83
Left errs -> mapM_ putStrLn errs
84
Right tree -> putStrLn $ show tree