-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.hs
171 lines (152 loc) · 4.46 KB
/
parser.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
module Parser(Aexp(..), Bexp(..), Stm(..), AST, parseProgram) where
import Combinators
import Control.Applicative
import Data.Char
--------------------------------------
-- ASTs
type AST = Stm
data Aexp = Num Integer
| Ident String
| StringLit String
| Add Aexp Aexp
| Mult Aexp Aexp
| Div Aexp Aexp
| Sub Aexp Aexp
| ReadInt -- TODO does not belong, move once things are exprs
deriving Show
data Bexp = Val Bool
| Eq Aexp Aexp
| Lteq Aexp Aexp
| Neg Bexp
| And Bexp Bexp
deriving Show
-- TODO make most (or all) things expression
data Stm = Assn String Aexp
| Skip
| Comp Stm Stm
| If Bexp Stm Stm
| While Bexp Stm
| Try Stm Stm
| Print Aexp
deriving Show
--------------------------------------
-- Parsing and IO
main = do ast <- fmap parseProgram getContents
case ast of
(Left err) -> putStrLn err
(Right ast) -> putStrLn (show ast)
parseProgram :: String -> Either String AST
parseProgram inp = case (parse stm inp) of
[] -> Left "Unable to parse"
[(output, remainder)] ->
if all isSpace remainder
then Right output
else Left ("Parsing failed. Unparsed Input:\n" ++ remainder)
--------------------------------------
-- Arithmetic Expressions
aexp :: Parser Aexp
aexp = do lhs <- term
do symbol "+"
rhs <- aexp
return (Add lhs rhs)
<|> do symbol "-"
rhs <- aexp
return (Sub lhs rhs)
<|> return lhs
term :: Parser Aexp
term = do lhs <- factor
do symbol "*"
rhs <- term
return (Mult lhs rhs)
<|> do symbol "/"
rhs <- term
return (Div lhs rhs)
<|> return lhs
factor :: Parser Aexp
factor = do symbol "("
expr <- aexp
symbol ")"
return expr
<|> do symbol "read_int"
return ReadInt
<|> do n <- integer
return (Num n)
<|> do id <- identifier
return (Ident id)
<|> do s <- stringLiteral
return (StringLit s)
--------------------------------------
-- Boolean Expressions
bexp :: Parser Bexp
bexp = do p <- predicate
return p
<|> do a1 <- aexp
symbol "="
a2 <- aexp
return (Eq a1 a2)
<|> do a1 <- aexp
symbol "<="
a2 <- aexp
return (Lteq a1 a2)
predicate :: Parser Bexp
predicate = do lhs <- clause
do and <- symbol "&&"
rhs <- predicate
return (And lhs rhs)
<|> return lhs
clause :: Parser Bexp
clause = do symbol "("
b <- bexp
symbol ")"
return b
<|> do t <- symbol "!"
b <- bexp
return (Neg b)
<|> do t <- symbol "true"
return (Val True)
<|> do t <- symbol "false"
return (Val False)
--------------------------------------
-- Statements
stm :: Parser Stm
stm = do many comment
s1 <- stmParen
do many comment
newline
many comment
s2 <- stm
many comment
return (Comp s1 s2)
<|> return s1
stmParen :: Parser Stm
stmParen = do symbol "("
s <- stm
symbol ")"
return s
<|> statement
statement :: Parser Stm
statement = do id <- identifier
symbol ":="
a <- aexp
return (Assn id a)
<|> do symbol "try"
s1 <- stm
symbol "catch"
s2 <- stm
return (Try s1 s2)
<|> do symbol "skip"
return Skip
<|> do symbol "if"
b <- bexp
symbol "then"
s1 <- stm
symbol "else"
s2 <- stm
return (If b s1 s2)
<|> do symbol "while"
b <- bexp
s <- stm
return (While b s)
<|> do symbol "print "
str <- aexp
return (Print str)