swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 1 | #include "Parser.h" |
2 | |||||
3 | #include <QDebug> | ||||
4 | |||||
5 | Parser::Parser(QString input) | ||||
6 | { | ||||
7 | _input = input; | ||||
8 | } | ||||
9 | |||||
10 | QChar Parser::peek() | ||||
11 | { | ||||
12 | if (atEnd()) | ||||
13 | return 0; | ||||
14 | |||||
15 | return _input[_pos]; | ||||
16 | } | ||||
17 | |||||
18 | QChar Parser::get() | ||||
19 | { | ||||
20 | return _input[_pos++]; | ||||
21 | } | ||||
22 | |||||
23 | bool Parser::atEnd() | ||||
24 | { | ||||
25 | return _pos >= _input.length(); | ||||
26 | } | ||||
27 | |||||
28 | void Parser::skip() | ||||
29 | { | ||||
30 | while (peek().isSpace()) | ||||
31 | get(); | ||||
32 | } | ||||
33 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 34 | template <typename T> |
35 | bool Parser::parseSymbol(T *node) | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 36 | { |
37 | skip(); | ||||
38 | |||||
39 | if (peek().isLetter()) | ||||
40 | { | ||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 41 | *node = T(get()); |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 42 | return true; |
43 | } | ||||
44 | |||||
45 | return false; | ||||
46 | } | ||||
47 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 48 | template <typename T> |
49 | bool Parser::parseIdentifier(T *node) | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 50 | { |
51 | skip(); | ||||
52 | |||||
53 | QString buffer; | ||||
54 | |||||
55 | if (peek().isUpper()) | ||||
56 | { | ||||
57 | while (peek().isLetter() || peek() == '-' || peek() == '_' || peek().isNumber()) | ||||
58 | { | ||||
59 | buffer += get(); | ||||
60 | } | ||||
61 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 62 | *node = T(buffer); |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 63 | return true; |
64 | } | ||||
65 | |||||
66 | return false; | ||||
67 | } | ||||
68 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 69 | template <typename T> |
70 | bool Parser::parseNumber(T *node) | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 71 | { |
72 | skip(); | ||||
73 | |||||
74 | QString buffer; | ||||
75 | |||||
76 | if (peek().isDigit()) | ||||
77 | { | ||||
78 | while (peek().isDigit()) | ||||
79 | buffer += get(); | ||||
80 | |||||
swissChili | 9dddbf7 | 2021-12-08 23:03:25 -0800 | [diff] [blame^] | 81 | *node = T(buffer, 10); |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 82 | return true; |
83 | } | ||||
84 | |||||
85 | return false; | ||||
86 | } | ||||
87 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 88 | template <typename T> |
89 | bool Parser::parseVariable(T *node) | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 90 | { |
91 | skip(); | ||||
92 | |||||
93 | int pos = _pos; | ||||
94 | |||||
95 | if (peek() == 's' || peek() == 'e' || peek() == 't') | ||||
96 | { | ||||
97 | char type = get().toLatin1(); | ||||
98 | |||||
99 | if (peek() == '.') | ||||
100 | { | ||||
101 | get(); | ||||
102 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 103 | T nameNode; |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 104 | |
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 105 | if (parseIdentifier(&nameNode)) |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 106 | { |
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 107 | *node = T(type, nameNode.name()); |
108 | return true; | ||||
109 | } | ||||
110 | else if (parseSymbol(&nameNode)) | ||||
111 | { | ||||
112 | *node = T(type, QString(nameNode.symbol())); | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 113 | return true; |
114 | } | ||||
115 | } | ||||
116 | } | ||||
117 | |||||
118 | _pos = pos; | ||||
119 | return false; | ||||
120 | } | ||||
121 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 122 | template <typename T> |
123 | QList<T> Parser::parseMany() | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 124 | { |
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 125 | QList<T > nodes; |
126 | T next; | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 127 | |
128 | while (parseOne(&next)) | ||||
129 | { | ||||
130 | nodes.append(next); | ||||
131 | } | ||||
132 | |||||
133 | return nodes; | ||||
134 | } | ||||
135 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 136 | template <typename T> |
137 | bool Parser::parseParens(T *node) | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 138 | { |
139 | skip(); | ||||
140 | |||||
141 | int pos = _pos; | ||||
142 | |||||
143 | if (peek() != '(') | ||||
144 | return false; | ||||
145 | |||||
146 | get(); | ||||
147 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 148 | QList<T> many = parseMany<T>(); |
149 | *node = T(many); | ||||
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 150 | |
151 | skip(); | ||||
152 | if (peek() != ')') | ||||
153 | { | ||||
154 | _pos = pos; | ||||
155 | return false; | ||||
156 | } | ||||
157 | |||||
158 | get(); | ||||
159 | |||||
160 | return true; | ||||
161 | } | ||||
162 | |||||
163 | bool Parser::parseFunction(AstNode *node) | ||||
164 | { | ||||
165 | skip(); | ||||
166 | |||||
167 | int pos = _pos; | ||||
168 | |||||
169 | if (peek() != '<') | ||||
170 | return false; | ||||
171 | |||||
172 | get(); | ||||
173 | |||||
174 | AstNode head; | ||||
175 | if (!parseIdentifier(&head)) | ||||
176 | { | ||||
177 | _pos = pos; | ||||
178 | return false; | ||||
179 | } | ||||
180 | |||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 181 | QList<AstNode> body = parseMany<AstNode>(); |
swissChili | c71acc6 | 2021-12-07 08:03:37 -0800 | [diff] [blame] | 182 | *node = AstNode(head.name(), body); |
183 | |||||
184 | skip(); | ||||
185 | if (peek() != '>') | ||||
186 | { | ||||
187 | _pos = pos; | ||||
188 | return false; | ||||
189 | } | ||||
190 | |||||
191 | get(); | ||||
192 | |||||
193 | return true; | ||||
194 | } | ||||
swissChili | 682e7bc | 2021-12-07 09:04:54 -0800 | [diff] [blame] | 195 | |
196 | template <> | ||||
197 | bool Parser::parseOne<Token>(Token *node) | ||||
198 | { | ||||
199 | return parseVariable(node) || | ||||
200 | parseNumber(node) || | ||||
201 | parseIdentifier(node) || | ||||
202 | parseSymbol(node) || | ||||
203 | parseParens(node); | ||||
204 | } | ||||
205 | |||||
206 | template <> | ||||
207 | bool Parser::parseOne<AstNode>(AstNode *node) | ||||
208 | { | ||||
209 | return parseFunction(node) || | ||||
210 | parseVariable(node) || | ||||
211 | parseNumber(node) || | ||||
212 | parseIdentifier(node) || | ||||
213 | parseSymbol(node) || | ||||
214 | parseParens(node); | ||||
215 | } | ||||
swissChili | 8a581c6 | 2021-12-07 13:29:21 -0800 | [diff] [blame] | 216 | |
217 | bool Parser::parseSentence(Sentence *sentence) | ||||
218 | { | ||||
219 | int pos = _pos; | ||||
220 | |||||
221 | QList<Token> pattern = parseMany<Token>(); | ||||
222 | |||||
223 | skip(); | ||||
224 | |||||
225 | if (get() != '=') | ||||
226 | { | ||||
227 | _pos = pos; | ||||
228 | return false; | ||||
229 | } | ||||
230 | |||||
231 | QList<AstNode> result = parseMany<AstNode>(); | ||||
232 | |||||
233 | skip(); | ||||
234 | |||||
235 | if (get() != ';') | ||||
236 | { | ||||
237 | _pos = pos; | ||||
238 | return false; | ||||
239 | } | ||||
240 | |||||
241 | *sentence = Sentence(pattern, result); | ||||
242 | return true; | ||||
243 | } | ||||
244 | |||||
245 | bool Parser::parseFunctionDefinition(Function *function) | ||||
246 | { | ||||
247 | int pos = _pos; | ||||
248 | |||||
249 | Token identifier; | ||||
250 | if (!parseIdentifier(&identifier)) | ||||
251 | { | ||||
252 | _pos = pos; | ||||
253 | return false; | ||||
254 | } | ||||
255 | |||||
256 | QString name = identifier.name(); | ||||
257 | Function func(name); | ||||
258 | |||||
259 | skip(); | ||||
260 | |||||
261 | if (get() != '{') | ||||
262 | { | ||||
263 | _pos = pos; | ||||
264 | return false; | ||||
265 | } | ||||
266 | |||||
267 | Sentence sentence; | ||||
268 | while (parseSentence(&sentence)) | ||||
269 | { | ||||
270 | func.addSentence(sentence); | ||||
271 | skip(); | ||||
272 | } | ||||
273 | |||||
274 | if (get() != '}') | ||||
275 | { | ||||
276 | _pos = pos; | ||||
277 | return false; | ||||
278 | } | ||||
279 | |||||
280 | *function = func; | ||||
281 | return true; | ||||
282 | } |