blob: 9b8f264a8b05e8705f96fc578d6e709c2bcf15c3 [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 {
swissChili847a78c2021-12-09 17:44:52 -0800200 // qDebug() << "parseMany one" << next;
swissChilic71acc62021-12-07 08:03:37 -0800201 nodes.append(next);
202 }
203
swissChili847a78c2021-12-09 17:44:52 -0800204 *list = nodes;
205
206 if (ret.status() == ParseResult::INCOMPLETE)
207 return ret;
208 else
209 return true;
swissChilic71acc62021-12-07 08:03:37 -0800210}
211
swissChili682e7bc2021-12-07 09:04:54 -0800212template <typename T>
swissChili847a78c2021-12-09 17:44:52 -0800213ParseResult Parser::parseParens(T *node)
swissChilic71acc62021-12-07 08:03:37 -0800214{
215 skip();
216
swissChili847a78c2021-12-09 17:44:52 -0800217 ParsePos pos = save();
swissChilic71acc62021-12-07 08:03:37 -0800218
219 if (peek() != '(')
220 return false;
221
222 get();
223
swissChili847a78c2021-12-09 17:44:52 -0800224 QList<T> many;
225 ParseResult ret = parseMany(&many);
226
swissChili682e7bc2021-12-07 09:04:54 -0800227 *node = T(many);
swissChilic71acc62021-12-07 08:03:37 -0800228
229 skip();
230 if (peek() != ')')
231 {
swissChili847a78c2021-12-09 17:44:52 -0800232 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ) in parenthesized list", save());
233 reset(pos);
234
235 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800236 }
237
238 get();
239
240 return true;
241}
242
swissChili847a78c2021-12-09 17:44:52 -0800243ParseResult Parser::parseFunction(AstNode *node)
swissChilic71acc62021-12-07 08:03:37 -0800244{
245 skip();
246
swissChili847a78c2021-12-09 17:44:52 -0800247 ParsePos pos = save();
248 ParseResult ret;
swissChilic71acc62021-12-07 08:03:37 -0800249
250 if (peek() != '<')
251 return false;
252
253 get();
254
255 AstNode head;
swissChili847a78c2021-12-09 17:44:52 -0800256 if (!(ret = parseIdentifier(&head)))
swissChilic71acc62021-12-07 08:03:37 -0800257 {
swissChili847a78c2021-12-09 17:44:52 -0800258 reset(pos);
259 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800260 }
261
swissChili847a78c2021-12-09 17:44:52 -0800262 QList<AstNode> body;
263 ret = parseMany(&body);
264
265 if (!ret)
266 {
267 reset(pos);
268 return ret;
269 }
270
swissChilic71acc62021-12-07 08:03:37 -0800271 *node = AstNode(head.name(), body);
272
273 skip();
274 if (peek() != '>')
275 {
swissChili847a78c2021-12-09 17:44:52 -0800276 ret = ParseResult(ParseResult::INCOMPLETE, "Expected >", save());
277 reset(pos);
278 return ret;
swissChilic71acc62021-12-07 08:03:37 -0800279 }
280
281 get();
282
283 return true;
284}
swissChili682e7bc2021-12-07 09:04:54 -0800285
286template <>
swissChili847a78c2021-12-09 17:44:52 -0800287ParseResult Parser::parseOne<Token>(Token *node)
swissChili682e7bc2021-12-07 09:04:54 -0800288{
289 return parseVariable(node) ||
290 parseNumber(node) ||
291 parseIdentifier(node) ||
292 parseSymbol(node) ||
293 parseParens(node);
294}
295
296template <>
swissChili847a78c2021-12-09 17:44:52 -0800297ParseResult Parser::parseOne<AstNode>(AstNode *node)
swissChili682e7bc2021-12-07 09:04:54 -0800298{
299 return parseFunction(node) ||
300 parseVariable(node) ||
301 parseNumber(node) ||
302 parseIdentifier(node) ||
303 parseSymbol(node) ||
304 parseParens(node);
305}
swissChili8a581c62021-12-07 13:29:21 -0800306
swissChili847a78c2021-12-09 17:44:52 -0800307ParseResult Parser::parseSentence(Sentence *sentence)
swissChili8a581c62021-12-07 13:29:21 -0800308{
swissChili847a78c2021-12-09 17:44:52 -0800309 ParsePos pos = save();
swissChili8a581c62021-12-07 13:29:21 -0800310
swissChili847a78c2021-12-09 17:44:52 -0800311 qDebug() << "Parsing sentence" << peek();
312
313 if (peek() == '}')
314 {
315 return false;
316 }
317
318 QList<Token> pattern;
319 ParseResult ret = parseMany(&pattern);
320
321 if (!ret)
322 {
323 qDebug() << "Many failed" << ret.message();
324 reset(pos);
325 return ret;
326 }
swissChili8a581c62021-12-07 13:29:21 -0800327
328 skip();
329
swissChili847a78c2021-12-09 17:44:52 -0800330 qDebug() << "will we get an =?" << peek();
331
swissChili8a581c62021-12-07 13:29:21 -0800332 if (get() != '=')
333 {
swissChili847a78c2021-12-09 17:44:52 -0800334 ret = ParseResult(ParseResult::INCOMPLETE, "Expected = in sentence", save());
335 reset(pos);
336 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800337 }
338
swissChili847a78c2021-12-09 17:44:52 -0800339 QList<AstNode> result;
340 ret = parseMany(&result);
341
342 if (!ret)
343 {
344 qDebug() << "sentence parseMany returned" << ret.message();
345 reset(pos);
346 return ret;
347 }
swissChili8a581c62021-12-07 13:29:21 -0800348
349 skip();
350
swissChili847a78c2021-12-09 17:44:52 -0800351 qDebug() << "end of sentence" << peek();
352
353 if (peek() != '}' && get() != ';')
swissChili8a581c62021-12-07 13:29:21 -0800354 {
swissChili847a78c2021-12-09 17:44:52 -0800355 ret = ParseResult(ParseResult::INCOMPLETE, "Expected ; or } after sentence", save());
356 reset(pos);
357 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800358 }
359
360 *sentence = Sentence(pattern, result);
swissChili847a78c2021-12-09 17:44:52 -0800361
swissChili8a581c62021-12-07 13:29:21 -0800362 return true;
363}
364
swissChili847a78c2021-12-09 17:44:52 -0800365ParseResult Parser::parseFunctionDefinition(Function *function)
swissChili8a581c62021-12-07 13:29:21 -0800366{
swissChili847a78c2021-12-09 17:44:52 -0800367 ParsePos pos = save();
368 ParseResult ret;
swissChili8a581c62021-12-07 13:29:21 -0800369
370 Token identifier;
swissChili847a78c2021-12-09 17:44:52 -0800371 if (!(ret = parseIdentifier(&identifier)))
swissChili8a581c62021-12-07 13:29:21 -0800372 {
swissChili847a78c2021-12-09 17:44:52 -0800373 reset(pos);
374 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800375 }
376
377 QString name = identifier.name();
378 Function func(name);
379
380 skip();
381
382 if (get() != '{')
383 {
swissChili847a78c2021-12-09 17:44:52 -0800384 reset(pos);
385 return false;
swissChili8a581c62021-12-07 13:29:21 -0800386 }
387
388 Sentence sentence;
swissChili847a78c2021-12-09 17:44:52 -0800389 while ((ret = parseSentence(&sentence)))
swissChili8a581c62021-12-07 13:29:21 -0800390 {
391 func.addSentence(sentence);
392 skip();
393 }
394
swissChili847a78c2021-12-09 17:44:52 -0800395 if (ret.status() == ParseResult::INCOMPLETE)
396 {
397 qDebug() << "Function incomplete";
398 reset(pos);
399 return ret;
400 }
401
swissChili8a581c62021-12-07 13:29:21 -0800402 if (get() != '}')
403 {
swissChili847a78c2021-12-09 17:44:52 -0800404 ret = ParseResult(ParseResult::INCOMPLETE, "Expected } at end of function");
405 reset(pos);
406 return ret;
swissChili8a581c62021-12-07 13:29:21 -0800407 }
408
swissChili847a78c2021-12-09 17:44:52 -0800409 qDebug() << "Function parsing succeeded";
410
swissChili8a581c62021-12-07 13:29:21 -0800411 *function = func;
412 return true;
413}