blob: 95bda1df29e20ca858728a6693c491ba37ba4b65 [file] [log] [blame]
swissChilic71acc62021-12-07 08:03:37 -08001#include "Parser.h"
2
3#include <QDebug>
4
swissChili847a78c2021-12-09 17:44:52 -08005ParseResult::ParseResult(bool okay)
6 : ParseResult((int)okay)
7{}
8
9ParseResult::ParseResult(int status, ParsePos pos)
10 : ParseResult(status, "", pos)
11{}
12
13ParseResult::ParseResult(int status, QString message, ParsePos pos)
14{
15 _status = status;
16 _message = message;
17 _pos = pos;
18}
19
20ParseResult::operator bool() const
21{
22 return _status == COMPLETE;
23}
24
25ParsePos ParseResult::pos() const
26{
27 return _pos;
28}
29
30QString ParseResult::message() const
31{
32 return _message;
33}
34
35int ParseResult::status() const
36{
37 return _status;
38}
39
swissChilic71acc62021-12-07 08:03:37 -080040Parser::Parser(QString input)
41{
42 _input = input;
43}
44
45QChar Parser::peek()
46{
47 if (atEnd())
48 return 0;
49
50 return _input[_pos];
51}
52
53QChar Parser::get()
54{
swissChili847a78c2021-12-09 17:44:52 -080055 QChar c = _input[_pos++];
56
57 if (c == '\n')
58 {
59 _line++;
60 _offset = 0;
61 }
62 else
63 {
64 _offset++;
65 }
66
67 return c;
swissChilic71acc62021-12-07 08:03:37 -080068}
69
70bool Parser::atEnd()
71{
72 return _pos >= _input.length();
73}
74
75void Parser::skip()
76{
77 while (peek().isSpace())
78 get();
79}
80
swissChili847a78c2021-12-09 17:44:52 -080081ParsePos Parser::save() const
82{
83 return ParsePos{_line, _pos, _offset};
84}
85
86void Parser::reset(ParsePos pos)
87{
88 _line = pos.line;
89 _pos = pos.pos;
90 _offset = pos.lineOffset;
91}
92
swissChili682e7bc2021-12-07 09:04:54 -080093template <typename T>
swissChili847a78c2021-12-09 17:44:52 -080094ParseResult Parser::parseSymbol(T *node)
swissChilic71acc62021-12-07 08:03:37 -080095{
96 skip();
97
98 if (peek().isLetter())
99 {
swissChili682e7bc2021-12-07 09:04:54 -0800100 *node = T(get());
swissChilic71acc62021-12-07 08:03:37 -0800101 return true;
102 }
103
104 return false;
105}
106
swissChili682e7bc2021-12-07 09:04:54 -0800107template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800108ParseResult Parser::parseIdentifier(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800109{
110 skip();
111
112 QString buffer;
113
114 if (peek().isUpper())
115 {
116 while (peek().isLetter() || peek() == '-' || peek() == '_' || peek().isNumber())
117 {
118 buffer += get();
119 }
120
swissChili682e7bc2021-12-07 09:04:54 -0800121 *node = T(buffer);
swissChilic71acc62021-12-07 08:03:37 -0800122 return true;
123 }
124
125 return false;
126}
127
swissChili682e7bc2021-12-07 09:04:54 -0800128template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800129ParseResult Parser::parseNumber(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800130{
131 skip();
132
133 QString buffer;
134
135 if (peek().isDigit())
136 {
137 while (peek().isDigit())
138 buffer += get();
139
swissChili1060c0e2021-12-09 09:46:42 -0800140 *node = T::fromInteger(buffer.toInt());
swissChilic71acc62021-12-07 08:03:37 -0800141 return true;
142 }
143
144 return false;
145}
146
swissChili682e7bc2021-12-07 09:04:54 -0800147template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800148ParseResult Parser::parseVariable(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800149{
150 skip();
151
swissChili847a78c2021-12-09 17:44:52 -0800152 ParsePos pos = save();
swissChilic71acc62021-12-07 08:03:37 -0800153
154 if (peek() == 's' || peek() == 'e' || peek() == 't')
155 {
156 char type = get().toLatin1();
157
158 if (peek() == '.')
159 {
160 get();
161
swissChili682e7bc2021-12-07 09:04:54 -0800162 T nameNode;
swissChilic71acc62021-12-07 08:03:37 -0800163
swissChili682e7bc2021-12-07 09:04:54 -0800164 if (parseIdentifier(&nameNode))
swissChilic71acc62021-12-07 08:03:37 -0800165 {
swissChili682e7bc2021-12-07 09:04:54 -0800166 *node = T(type, nameNode.name());
167 return true;
168 }
169 else if (parseSymbol(&nameNode))
170 {
171 *node = T(type, QString(nameNode.symbol()));
swissChilic71acc62021-12-07 08:03:37 -0800172 return true;
173 }
swissChili847a78c2021-12-09 17:44:52 -0800174 else
175 {
176 ParseResult ret(ParseResult::INCOMPLETE,
177 "Expected identifier or symbol after . in variable",
178 pos);
179
180 reset(pos);
181
182 return ret;
183 }
swissChilic71acc62021-12-07 08:03:37 -0800184 }
185 }
186
swissChili847a78c2021-12-09 17:44:52 -0800187 reset(pos);
swissChilic71acc62021-12-07 08:03:37 -0800188 return false;
189}
190
swissChili682e7bc2021-12-07 09:04:54 -0800191template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800192ParseResult Parser::parseMany(QList<T> *list)
swissChilic71acc62021-12-07 08:03:37 -0800193{
swissChili847a78c2021-12-09 17:44:52 -0800194 QList<T> nodes;
swissChili682e7bc2021-12-07 09:04:54 -0800195 T next;
swissChili847a78c2021-12-09 17:44:52 -0800196 ParseResult ret;
swissChilic71acc62021-12-07 08:03:37 -0800197
swissChili847a78c2021-12-09 17:44:52 -0800198 while ((ret = parseOne(&next)))
swissChilic71acc62021-12-07 08:03:37 -0800199 {
200 nodes.append(next);
201 }
202
swissChili847a78c2021-12-09 17:44:52 -0800203 *list = nodes;
204
205 if (ret.status() == ParseResult::INCOMPLETE)
206 return ret;
207 else
208 return true;
swissChilic71acc62021-12-07 08:03:37 -0800209}
210
swissChili682e7bc2021-12-07 09:04:54 -0800211template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800212ParseResult Parser::parseParens(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800213{
214 skip();
215
swissChili847a78c2021-12-09 17:44:52 -0800216 ParsePos pos = save();
swissChilic71acc62021-12-07 08:03:37 -0800217
218 if (peek() != '(')
219 return false;
220
221 get();
222
swissChili847a78c2021-12-09 17:44:52 -0800223 QList<T> many;
224 ParseResult ret = parseMany(&many);
225
swissChili682e7bc2021-12-07 09:04:54 -0800226 *node = T(many);
swissChilic71acc62021-12-07 08:03:37 -0800227
228 skip();
229 if (peek() != ')')
230 {
swissChili847a78c2021-12-09 17:44:52 -0800231 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ) in parenthesized list", save());
232 reset(pos);
233
234 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800235 }
236
237 get();
238
239 return true;
240}
241
swissChili847a78c2021-12-09 17:44:52 -0800242ParseResult Parser::parseFunction(AstNode *node)
swissChilic71acc62021-12-07 08:03:37 -0800243{
244 skip();
245
swissChili847a78c2021-12-09 17:44:52 -0800246 ParsePos pos = save();
247 ParseResult ret;
swissChilic71acc62021-12-07 08:03:37 -0800248
249 if (peek() != '<')
250 return false;
251
252 get();
253
254 AstNode head;
swissChili847a78c2021-12-09 17:44:52 -0800255 if (!(ret = parseIdentifier(&head)))
swissChilic71acc62021-12-07 08:03:37 -0800256 {
swissChili847a78c2021-12-09 17:44:52 -0800257 reset(pos);
258 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800259 }
260
swissChili847a78c2021-12-09 17:44:52 -0800261 QList<AstNode> body;
262 ret = parseMany(&body);
263
264 if (!ret)
265 {
266 reset(pos);
267 return ret;
268 }
269
swissChilic71acc62021-12-07 08:03:37 -0800270 *node = AstNode(head.name(), body);
271
272 skip();
273 if (peek() != '>')
274 {
swissChili847a78c2021-12-09 17:44:52 -0800275 ret = ParseResult(ParseResult::INCOMPLETE, "Expected >", save());
276 reset(pos);
277 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800278 }
279
280 get();
281
282 return true;
283}
swissChili682e7bc2021-12-07 09:04:54 -0800284
285template <>
swissChili847a78c2021-12-09 17:44:52 -0800286ParseResult Parser::parseOne<Token>(Token *node)
swissChili682e7bc2021-12-07 09:04:54 -0800287{
288 return parseVariable(node) ||
289 parseNumber(node) ||
290 parseIdentifier(node) ||
291 parseSymbol(node) ||
292 parseParens(node);
293}
294
295template <>
swissChili847a78c2021-12-09 17:44:52 -0800296ParseResult Parser::parseOne<AstNode>(AstNode *node)
swissChili682e7bc2021-12-07 09:04:54 -0800297{
298 return parseFunction(node) ||
299 parseVariable(node) ||
300 parseNumber(node) ||
301 parseIdentifier(node) ||
302 parseSymbol(node) ||
303 parseParens(node);
304}
swissChili8a581c62021-12-07 13:29:21 -0800305
swissChili847a78c2021-12-09 17:44:52 -0800306ParseResult Parser::parseSentence(Sentence *sentence)
swissChili8a581c62021-12-07 13:29:21 -0800307{
swissChili847a78c2021-12-09 17:44:52 -0800308 ParsePos pos = save();
swissChili8a581c62021-12-07 13:29:21 -0800309
swissChili847a78c2021-12-09 17:44:52 -0800310 if (peek() == '}')
311 {
312 return false;
313 }
314
315 QList<Token> pattern;
316 ParseResult ret = parseMany(&pattern);
317
318 if (!ret)
319 {
swissChili847a78c2021-12-09 17:44:52 -0800320 reset(pos);
321 return ret;
322 }
swissChili8a581c62021-12-07 13:29:21 -0800323
324 skip();
325
326 if (get() != '=')
327 {
swissChili847a78c2021-12-09 17:44:52 -0800328 ret = ParseResult(ParseResult::INCOMPLETE, "Expected = in sentence", save());
329 reset(pos);
330 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800331 }
332
swissChili847a78c2021-12-09 17:44:52 -0800333 QList<AstNode> result;
334 ret = parseMany(&result);
335
336 if (!ret)
337 {
swissChili847a78c2021-12-09 17:44:52 -0800338 reset(pos);
339 return ret;
340 }
swissChili8a581c62021-12-07 13:29:21 -0800341
342 skip();
343
swissChili847a78c2021-12-09 17:44:52 -0800344 if (peek() != '}' && get() != ';')
swissChili8a581c62021-12-07 13:29:21 -0800345 {
swissChili847a78c2021-12-09 17:44:52 -0800346 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ; or } after sentence", save());
347 reset(pos);
348 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800349 }
350
351 *sentence = Sentence(pattern, result);
swissChili847a78c2021-12-09 17:44:52 -0800352
swissChili8a581c62021-12-07 13:29:21 -0800353 return true;
354}
355
swissChili847a78c2021-12-09 17:44:52 -0800356ParseResult Parser::parseFunctionDefinition(Function *function)
swissChili8a581c62021-12-07 13:29:21 -0800357{
swissChili847a78c2021-12-09 17:44:52 -0800358 ParsePos pos = save();
359 ParseResult ret;
swissChili8a581c62021-12-07 13:29:21 -0800360
361 Token identifier;
swissChili847a78c2021-12-09 17:44:52 -0800362 if (!(ret = parseIdentifier(&identifier)))
swissChili8a581c62021-12-07 13:29:21 -0800363 {
swissChili847a78c2021-12-09 17:44:52 -0800364 reset(pos);
365 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800366 }
367
368 QString name = identifier.name();
369 Function func(name);
370
371 skip();
372
373 if (get() != '{')
374 {
swissChili847a78c2021-12-09 17:44:52 -0800375 reset(pos);
376 return false;
swissChili8a581c62021-12-07 13:29:21 -0800377 }
378
379 Sentence sentence;
swissChili847a78c2021-12-09 17:44:52 -0800380 while ((ret = parseSentence(&sentence)))
swissChili8a581c62021-12-07 13:29:21 -0800381 {
382 func.addSentence(sentence);
383 skip();
384 }
385
swissChili847a78c2021-12-09 17:44:52 -0800386 if (ret.status() == ParseResult::INCOMPLETE)
387 {
swissChili847a78c2021-12-09 17:44:52 -0800388 reset(pos);
389 return ret;
390 }
391
swissChili8a581c62021-12-07 13:29:21 -0800392 if (get() != '}')
393 {
swissChili847a78c2021-12-09 17:44:52 -0800394 ret = ParseResult(ParseResult::INCOMPLETE, "Expected } at end of function");
395 reset(pos);
396 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800397 }
398
399 *function = func;
400 return true;
401}