blob: 41f6727683d5f9711cf151143f50624b1933f426 [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;
swissChili323883d2022-02-20 16:35:23 -080016 _message = message;
swissChili847a78c2021-12-09 17:44:52 -080017 _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
swissChili323883d2022-02-20 16:35:23 -080081QString Parser::line(int n) const
82{
83 return _input.split("\n")[n];
84}
85
swissChili847a78c2021-12-09 17:44:52 -080086ParsePos Parser::save() const
87{
88 return ParsePos{_line, _pos, _offset};
89}
90
91void Parser::reset(ParsePos pos)
92{
93 _line = pos.line;
94 _pos = pos.pos;
95 _offset = pos.lineOffset;
96}
97
swissChili682e7bc2021-12-07 09:04:54 -080098template <typename T>
swissChili847a78c2021-12-09 17:44:52 -080099ParseResult Parser::parseSymbol(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800100{
101 skip();
102
103 if (peek().isLetter())
104 {
swissChili682e7bc2021-12-07 09:04:54 -0800105 *node = T(get());
swissChilic71acc62021-12-07 08:03:37 -0800106 return true;
107 }
108
109 return false;
110}
111
swissChili682e7bc2021-12-07 09:04:54 -0800112template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800113ParseResult Parser::parseIdentifier(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800114{
115 skip();
116
117 QString buffer;
118
119 if (peek().isUpper())
120 {
121 while (peek().isLetter() || peek() == '-' || peek() == '_' || peek().isNumber())
122 {
123 buffer += get();
124 }
125
swissChili682e7bc2021-12-07 09:04:54 -0800126 *node = T(buffer);
swissChilic71acc62021-12-07 08:03:37 -0800127 return true;
128 }
129
130 return false;
131}
132
swissChili682e7bc2021-12-07 09:04:54 -0800133template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800134ParseResult Parser::parseNumber(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800135{
136 skip();
137
138 QString buffer;
139
140 if (peek().isDigit())
141 {
142 while (peek().isDigit())
143 buffer += get();
144
swissChili1060c0e2021-12-09 09:46:42 -0800145 *node = T::fromInteger(buffer.toInt());
swissChilic71acc62021-12-07 08:03:37 -0800146 return true;
147 }
148
149 return false;
150}
151
swissChili682e7bc2021-12-07 09:04:54 -0800152template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800153ParseResult Parser::parseVariable(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800154{
155 skip();
156
swissChili847a78c2021-12-09 17:44:52 -0800157 ParsePos pos = save();
swissChilic71acc62021-12-07 08:03:37 -0800158
159 if (peek() == 's' || peek() == 'e' || peek() == 't')
160 {
161 char type = get().toLatin1();
162
163 if (peek() == '.')
164 {
165 get();
166
swissChili682e7bc2021-12-07 09:04:54 -0800167 T nameNode;
swissChilic71acc62021-12-07 08:03:37 -0800168
swissChili682e7bc2021-12-07 09:04:54 -0800169 if (parseIdentifier(&nameNode))
swissChilic71acc62021-12-07 08:03:37 -0800170 {
swissChili682e7bc2021-12-07 09:04:54 -0800171 *node = T(type, nameNode.name());
172 return true;
173 }
174 else if (parseSymbol(&nameNode))
175 {
176 *node = T(type, QString(nameNode.symbol()));
swissChilic71acc62021-12-07 08:03:37 -0800177 return true;
178 }
swissChili847a78c2021-12-09 17:44:52 -0800179 else
180 {
181 ParseResult ret(ParseResult::INCOMPLETE,
182 "Expected identifier or symbol after . in variable",
swissChili323883d2022-02-20 16:35:23 -0800183 save());
swissChili847a78c2021-12-09 17:44:52 -0800184
185 reset(pos);
186
187 return ret;
188 }
swissChilic71acc62021-12-07 08:03:37 -0800189 }
190 }
191
swissChili847a78c2021-12-09 17:44:52 -0800192 reset(pos);
swissChilic71acc62021-12-07 08:03:37 -0800193 return false;
194}
195
swissChili682e7bc2021-12-07 09:04:54 -0800196template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800197ParseResult Parser::parseMany(QList<T> *list)
swissChilic71acc62021-12-07 08:03:37 -0800198{
swissChili847a78c2021-12-09 17:44:52 -0800199 QList<T> nodes;
swissChili682e7bc2021-12-07 09:04:54 -0800200 T next;
swissChili847a78c2021-12-09 17:44:52 -0800201 ParseResult ret;
swissChilic71acc62021-12-07 08:03:37 -0800202
swissChili847a78c2021-12-09 17:44:52 -0800203 while ((ret = parseOne(&next)))
swissChilic71acc62021-12-07 08:03:37 -0800204 {
205 nodes.append(next);
206 }
207
swissChili847a78c2021-12-09 17:44:52 -0800208 *list = nodes;
209
210 if (ret.status() == ParseResult::INCOMPLETE)
211 return ret;
212 else
213 return true;
swissChilic71acc62021-12-07 08:03:37 -0800214}
215
swissChili682e7bc2021-12-07 09:04:54 -0800216template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800217ParseResult Parser::parseParens(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800218{
219 skip();
220
swissChili847a78c2021-12-09 17:44:52 -0800221 ParsePos pos = save();
swissChilic71acc62021-12-07 08:03:37 -0800222
223 if (peek() != '(')
224 return false;
225
226 get();
227
swissChili847a78c2021-12-09 17:44:52 -0800228 QList<T> many;
229 ParseResult ret = parseMany(&many);
230
swissChili682e7bc2021-12-07 09:04:54 -0800231 *node = T(many);
swissChilic71acc62021-12-07 08:03:37 -0800232
233 skip();
234 if (peek() != ')')
235 {
swissChili847a78c2021-12-09 17:44:52 -0800236 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ) in parenthesized list", save());
237 reset(pos);
238
239 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800240 }
241
242 get();
243
244 return true;
245}
246
swissChili847a78c2021-12-09 17:44:52 -0800247ParseResult Parser::parseFunction(AstNode *node)
swissChilic71acc62021-12-07 08:03:37 -0800248{
249 skip();
250
swissChili847a78c2021-12-09 17:44:52 -0800251 ParsePos pos = save();
252 ParseResult ret;
swissChilic71acc62021-12-07 08:03:37 -0800253
254 if (peek() != '<')
255 return false;
256
257 get();
258
259 AstNode head;
swissChili847a78c2021-12-09 17:44:52 -0800260 if (!(ret = parseIdentifier(&head)))
swissChilic71acc62021-12-07 08:03:37 -0800261 {
swissChili323883d2022-02-20 16:35:23 -0800262 ParsePos endPos = save();
swissChili847a78c2021-12-09 17:44:52 -0800263 reset(pos);
swissChili323883d2022-02-20 16:35:23 -0800264 return ParseResult(ParseResult::INCOMPLETE, "Expected identifier following < in function call", endPos);
swissChilic71acc62021-12-07 08:03:37 -0800265 }
266
swissChili847a78c2021-12-09 17:44:52 -0800267 QList<AstNode> body;
268 ret = parseMany(&body);
269
270 if (!ret)
271 {
272 reset(pos);
273 return ret;
274 }
275
swissChilic71acc62021-12-07 08:03:37 -0800276 *node = AstNode(head.name(), body);
277
278 skip();
279 if (peek() != '>')
280 {
swissChili847a78c2021-12-09 17:44:52 -0800281 ret = ParseResult(ParseResult::INCOMPLETE, "Expected >", save());
282 reset(pos);
283 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800284 }
285
286 get();
287
288 return true;
289}
swissChili682e7bc2021-12-07 09:04:54 -0800290
291template <>
swissChili847a78c2021-12-09 17:44:52 -0800292ParseResult Parser::parseOne<Token>(Token *node)
swissChili682e7bc2021-12-07 09:04:54 -0800293{
swissChili323883d2022-02-20 16:35:23 -0800294 ParseResult ret;
295
296 if ((ret = parseVariable(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
297 return ret;
298 if ((ret = parseNumber(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
299 return ret;
300 if ((ret = parseIdentifier(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
301 return ret;
302 if ((ret = parseSymbol(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
303 return ret;
304 return parseParens(node);
swissChili682e7bc2021-12-07 09:04:54 -0800305}
306
307template <>
swissChili847a78c2021-12-09 17:44:52 -0800308ParseResult Parser::parseOne<AstNode>(AstNode *node)
swissChili682e7bc2021-12-07 09:04:54 -0800309{
swissChili323883d2022-02-20 16:35:23 -0800310 ParseResult ret;
311
312 if ((ret = parseFunction(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
313 return ret;
314 if ((ret = parseVariable(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
315 return ret;
316 if ((ret = parseNumber(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
317 return ret;
318 if ((ret = parseIdentifier(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
319 return ret;
320 if ((ret = parseSymbol(node)).status() == ParseResult::COMPLETE || ret.status() == ParseResult::INCOMPLETE)
321 return ret;
322 return parseParens(node);
swissChili682e7bc2021-12-07 09:04:54 -0800323}
swissChili8a581c62021-12-07 13:29:21 -0800324
swissChili847a78c2021-12-09 17:44:52 -0800325ParseResult Parser::parseSentence(Sentence *sentence)
swissChili8a581c62021-12-07 13:29:21 -0800326{
swissChili847a78c2021-12-09 17:44:52 -0800327 ParsePos pos = save();
swissChili8a581c62021-12-07 13:29:21 -0800328
swissChili847a78c2021-12-09 17:44:52 -0800329 if (peek() == '}')
330 {
331 return false;
332 }
333
334 QList<Token> pattern;
335 ParseResult ret = parseMany(&pattern);
336
337 if (!ret)
338 {
swissChili847a78c2021-12-09 17:44:52 -0800339 reset(pos);
340 return ret;
341 }
swissChili8a581c62021-12-07 13:29:21 -0800342
343 skip();
344
345 if (get() != '=')
346 {
swissChili847a78c2021-12-09 17:44:52 -0800347 ret = ParseResult(ParseResult::INCOMPLETE, "Expected = in sentence", save());
348 reset(pos);
349 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800350 }
351
swissChili847a78c2021-12-09 17:44:52 -0800352 QList<AstNode> result;
353 ret = parseMany(&result);
354
355 if (!ret)
356 {
swissChili847a78c2021-12-09 17:44:52 -0800357 reset(pos);
358 return ret;
359 }
swissChili8a581c62021-12-07 13:29:21 -0800360
361 skip();
362
swissChili847a78c2021-12-09 17:44:52 -0800363 if (peek() != '}' && get() != ';')
swissChili8a581c62021-12-07 13:29:21 -0800364 {
swissChili847a78c2021-12-09 17:44:52 -0800365 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ; or } after sentence", save());
366 reset(pos);
367 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800368 }
369
370 *sentence = Sentence(pattern, result);
swissChili847a78c2021-12-09 17:44:52 -0800371
swissChili8a581c62021-12-07 13:29:21 -0800372 return true;
373}
374
swissChili847a78c2021-12-09 17:44:52 -0800375ParseResult Parser::parseFunctionDefinition(Function *function)
swissChili8a581c62021-12-07 13:29:21 -0800376{
swissChili847a78c2021-12-09 17:44:52 -0800377 ParsePos pos = save();
378 ParseResult ret;
swissChili8a581c62021-12-07 13:29:21 -0800379
380 Token identifier;
swissChili847a78c2021-12-09 17:44:52 -0800381 if (!(ret = parseIdentifier(&identifier)))
swissChili8a581c62021-12-07 13:29:21 -0800382 {
swissChili847a78c2021-12-09 17:44:52 -0800383 reset(pos);
384 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800385 }
386
387 QString name = identifier.name();
388 Function func(name);
389
390 skip();
391
392 if (get() != '{')
393 {
swissChili847a78c2021-12-09 17:44:52 -0800394 reset(pos);
395 return false;
swissChili8a581c62021-12-07 13:29:21 -0800396 }
397
398 Sentence sentence;
swissChili847a78c2021-12-09 17:44:52 -0800399 while ((ret = parseSentence(&sentence)))
swissChili8a581c62021-12-07 13:29:21 -0800400 {
401 func.addSentence(sentence);
402 skip();
403 }
404
swissChili323883d2022-02-20 16:35:23 -0800405 if (ret.status() == ParseResult::INCOMPLETE)
swissChili847a78c2021-12-09 17:44:52 -0800406 {
swissChili847a78c2021-12-09 17:44:52 -0800407 reset(pos);
408 return ret;
409 }
410
swissChili8a581c62021-12-07 13:29:21 -0800411 if (get() != '}')
412 {
swissChili323883d2022-02-20 16:35:23 -0800413 ret = ParseResult(ParseResult::INCOMPLETE, "Expected } at end of function", save());
swissChili847a78c2021-12-09 17:44:52 -0800414 reset(pos);
415 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800416 }
417
418 *function = func;
419 return true;
420}
swissChili323883d2022-02-20 16:35:23 -0800421
422ParsePos::operator QString()
423{
424 return QString::number(line) + ":" + QString::number(lineOffset);
425}