-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgramStructure.hs
More file actions
217 lines (204 loc) · 8.64 KB
/
ProgramStructure.hs
File metadata and controls
217 lines (204 loc) · 8.64 KB
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
module ProgramStructure where
import Data.List (intercalate)
import Data.Maybe (fromMaybe)
import Tokens
-- Utilities
showsLines :: Show a => [a] -> String -> String
showsLines linesList = (++) (unlines $ map show linesList)
-- Data types for main program constructs
data Class
= Class { clsName :: !String
, clsVars :: ![ClassVarDec]
, clsSubs :: ![SubDec] }
instance Show Class where
show c = "<class>\n\
\<keyword> class </keyword>\n\
\<identifier> " ++ clsName c ++ " </identifier>\n\
\<symbol> { </symbol>\n"
++ (showsLines (clsVars c)
. showsLines (clsSubs c))
"<symbol> } </symbol>\n\
\</class>"
newtype ClassVarDec = ClassVarDec [Token]
instance Show ClassVarDec where
show (ClassVarDec vars) = "<classVarDec>\n"
++ showsLines vars
"</classVarDec>"
data SubDec
= SubDec { subKind :: !String
, subType :: !Token
, subClass :: !String
, clsFields :: !Int
, subName :: !String
, subParams :: ![Token]
, subBody :: !SubBody }
instance Show SubDec where
show sd = "<subroutineDec>\n\
\<keyword> " ++ subKind sd ++ " </keyword>\n"
++ shows (subType sd) "\n\
\<identifier> " ++ subName sd ++ " </identifier>\n\
\<symbol> ( </symbol>\n\
\<parameterList>\n"
++ showsLines (subParams sd)
"</parameterList>\n\
\<symbol> ) </symbol>\n"
++ shows (subBody sd) "\n\
\</subroutineDec>"
data SubBody
= SubBody { varCount :: !Int
, subVars :: ![VarDec]
, subStatements :: !Statements }
instance Show SubBody where
show sb = "<subroutineBody nVars = \""
++ show (varCount sb) ++ "\">\n\
\<symbol> { </symbol>\n"
++ (showsLines (subVars sb)
. shows (subStatements sb)) "\n\
\<symbol> } </symbol>\n\
\</subroutineBody>"
newtype VarDec = VarDec [Token]
instance Show VarDec where
show (VarDec vars) = "<varDec>\n"
++ showsLines vars
"</varDec>"
-- Data types for statements
newtype Statements = Statements [Statement]
instance Show Statements where
show (Statements stms) = "<statements>\n"
++ showsLines stms
"</statements>"
data Statement
= LetArr !String !String !Expression !Expression
| LetVar !String !String !Expression
| If !Expression !Statements (Maybe Statements) !String
| While !Expression !Statements !String
| Do !SubCall
| Return (Maybe Expression)
instance Show Statement where
show (LetArr array push index value) =
"<letStatement>\n\
\<keyword> let </keyword>\n\
\<identifier push = \"" ++ push
++ "\"> "++ array ++ " </identifier>\n\
\<symbol> [ </symbol>\n"
++ shows index "\n\
\<symbol> ] </symbol>\n\
\<symbol> = </symbol>\n"
++ shows value "\n\
\<symbol> ; </symbol>\n\
\</letStatement>"
show (LetVar var pop value) = "<letStatement>\n\
\<keyword> let </keyword>\n\
\<identifier pop = \"" ++ pop
++ "\"> " ++ var ++ " </identifier>\n\
\<symbol> = </symbol>\n"
++ shows value "\n\
\<symbol> ; </symbol>\n\
\</letStatement>"
show (If cond thenDo elseDo labelID) = "<ifStatement labelID = \""
++ labelID ++ "\">\n\
\<keyword> if </keyword>\n\
\<symbol> ( </symbol>\n"
++ shows cond "\n\
\<symbol> ) </symbol>\n\
\<symbol> { </symbol>\n"
++ shows thenDo "\n\
\<symbol> } </symbol>\n"
++ showsElse elseDo
"</ifStatement>"
where
showsElse (Just s) = (++) ("<keyword> else </keyword>\n\
\<symbol> { </symbol>\n"
++ shows s "\n\
\<symbol> } </symbol>\n")
showsElse Nothing = (++) ""
show (While cond loop labelID) = "<whileStatement labelID = \""
++ labelID ++ "\">\n\
\<keyword> while </keyword>\n\
\<symbol> ( </symbol>\n"
++ shows cond "\n\
\<symbol> ) </symbol>\n\
\<symbol> { </symbol>\n"
++ shows loop "\n\
\<symbol> } </symbol>\n\
\</whileStatement>"
show (Do subCall) = "<doStatement>\n\
\<keyword> do </keyword>\n"
++ shows subCall "\n\
\<symbol> ; </symbol>\n\
\</doStatement>"
show (Return mValue) = "<returnStatement>\n\
\<keyword> return </keyword>\n"
++ showsMaybeExp mValue
"<symbol> ; </symbol>\n\
\</returnStatement>"
where
showsMaybeExp (Just e) = (++) (shows e "\n")
showsMaybeExp Nothing = (++) ""
data SubCall =
SubCall !String (Maybe String) !Bool !String !String !ExpressionList
instance Show SubCall where
show (SubCall name mPush explicitName cls sub args) =
let showsName = if explicitName
then (++) ("<identifier push = \"" ++ fromMaybe "" mPush
++ "\"> " ++ name ++" </identifier>\n\
\<symbol> . </symbol>\n")
else (++) ""
in showsName
"<identifier class = \"" ++ cls
++ "\"> " ++ sub ++ " </identifier>\n\
\<symbol> ( </symbol>\n"
++ shows args "\n\
\<symbol> ) </symbol>"
-- Data types for expressions
newtype ExpressionList = ExpressionList [Expression]
instance Show ExpressionList where
show (ExpressionList []) = "<expressionList>\n\
\</expressionList>"
show (ExpressionList exprs) =
"<expressionList>\n"
++ (intercalate "\n<symbol> , </symbol>\n" $ map show exprs)
++ "\n</expressionList>"
data Expression = Expression !Term (Maybe (Token, Term))
instance Show Expression where
show (Expression term1 mFollow) = "<expression>\n"
++ shows term1 "\n"
++ showsFollow mFollow
"</expression>"
where
showsFollow (Just (op, term2)) = (++) (shows op "\n" ++ shows term2 "\n")
showsFollow Nothing = (++) ""
data Term
= Call !SubCall
| Arr !String !String !Expression
| Var !String !String
| Unary !Token !Term
| Const !Token
| Parens !Expression
instance Show Term where
show (Call subCall) = "<term>\n"
++ shows subCall "\n\
\</term>"
show (Arr arr push index) = "<term>\n\
\<identifier push = \"" ++ push
++ "\"> " ++ arr ++ " </identifier>\n\
\<symbol> [ </symbol>\n"
++ shows index "\n\
\<symbol> ] </symbol>\n\
\</term>"
show (Var var push) = "<term>\n\
\<identifier push = \"" ++ push
++ "\"> " ++ var ++ " </identifier>\n\
\</term>"
show (Unary op term) = "<term>\n"
++ shows op "\n"
++ shows term "\n\
\</term>"
show (Const c) = "<term>\n"
++ shows c "\n\
\</term>"
show (Parens expr) = "<term>\n\
\<symbol> ( </symbol>\n"
++ shows expr "\n\
\<symbol> ) </symbol>\n\
\</term>"