MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
parser.cpp
Go to the documentation of this file.
1
6#include "parser.hpp"
7#include <algorithm>
8#include <cctype>
9
10namespace pascal {
11
13 auto &toks = scanner.getTokens();
14 for (size_t i = 0; i < toks.size();) {
15 if (toks[i].getTokenValue() == "{") {
16 size_t start = i;
17 ++i;
18 while (i < toks.size() && toks[i].getTokenValue() != "}") {
19 ++i;
20 }
21 if (i < toks.size()) {
22 ++i; // skip closing }
23 }
24 toks.erase(toks.begin() + static_cast<int64_t>(start),
25 toks.begin() + static_cast<int64_t>(i));
26 i = start;
27 } else {
28 ++i;
29 }
30 }
31 }
32
33 void PascalParser::error(const std::string &message) {
34 throw ParseException("Parse error: " + message + (token ? " at '" + token->getTokenValue() + "'" : " at end of input"));
35 }
36
37 void PascalParser::expectToken(const std::string &expected) {
38 if (!peekIs(expected))
39 error("Expected '" + expected + "'" + " on Line: " + std::to_string(token->getLine()));
40 }
41
43 if (!peekIs(expected))
44 error("Expected " + tokenTypeToString(expected));
45 }
46
47 std::unique_ptr<ProgramNode> PascalParser::parseProgram() {
48 expectToken("program");
49 int lineNum = token->getLine();
50 next();
52 std::string programName = token->getTokenValue();
53 next();
54 expectToken(";");
55 next();
56 std::vector<std::string> usesList;
57 if (peekIs("uses")) {
58 next();
60 usesList.push_back(token->getTokenValue());
61 next();
62 while (peekIs(",")) {
63 next();
65 usesList.push_back(token->getTokenValue());
66 next();
67 }
68 expectToken(";");
69 next();
70 }
71 auto block = parseBlock();
72 expectToken(".");
73 auto programNode = std::make_unique<ProgramNode>(programName, std::move(block));
74 programNode->uses = std::move(usesList);
75 programNode->setLineNumber(lineNum);
76 return programNode;
77 }
78
79 bool PascalParser::match(const std::string &s) {
80 if (peekIs(s)) {
81 next();
82 return true;
83 }
84 return false;
85 }
86
88 if (!token)
89 return false;
90 std::string val = token->getTokenValue();
91 std::transform(val.begin(), val.end(), val.begin(), ::tolower);
92 return val == "unit";
93 }
94
95 std::unique_ptr<UnitNode> PascalParser::parseUnit() {
96 expectToken("unit");
97 int lineNum = token->getLine();
98 next();
100 std::string unitName = token->getTokenValue();
101 next();
102 expectToken(";");
103 next();
104
105 auto unitNode = std::make_unique<UnitNode>(unitName);
106 unitNode->setLineNumber(lineNum);
107
108 // interface section
109 expectToken("interface");
110 next();
111
112 // optional uses clause in interface
113 std::vector<std::string> usesList;
114 if (peekIs("uses")) {
115 next();
117 usesList.push_back(token->getTokenValue());
118 next();
119 while (peekIs(",")) {
120 next();
122 usesList.push_back(token->getTokenValue());
123 next();
124 }
125 expectToken(";");
126 next();
127 }
128 unitNode->uses = std::move(usesList);
129
130 // parse interface declarations (forward proc/func signatures)
131 unitNode->interfaceDecls = parseInterfaceDeclarations();
132
133 // implementation section
134 expectToken("implementation");
135 next();
136
137 // optional uses clause in implementation (additional modules)
138 if (peekIs("uses")) {
139 next();
141 unitNode->uses.push_back(token->getTokenValue());
142 next();
143 while (peekIs(",")) {
144 next();
146 unitNode->uses.push_back(token->getTokenValue());
147 next();
148 }
149 expectToken(";");
150 next();
151 }
152
153 // parse implementation declarations (full proc/func with bodies, vars, consts, types)
154 unitNode->implDecls = parseDeclarations();
155
156 // end.
157 expectToken("end");
158 next();
159 expectToken(".");
160 return unitNode;
161 }
162
163 std::vector<std::unique_ptr<ASTNode>> PascalParser::parseInterfaceDeclarations() {
164 std::vector<std::unique_ptr<ASTNode>> decls;
165 while (peekIs("procedure") || peekIs("function") || peekIs("type") || peekIs("const") || peekIs("var")) {
166 if (peekIs("procedure")) {
167 decls.push_back(parseProcedureForwardDecl());
168 } else if (peekIs("function")) {
169 decls.push_back(parseFunctionForwardDecl());
170 } else if (peekIs("type")) {
171 decls.push_back(parseTypeDeclaration());
172 } else if (peekIs("const")) {
173 decls.push_back(parseConstDeclaration());
174 } else if (peekIs("var")) {
175 if (match("var")) {
176 while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue())) {
177 auto decl = parseVarDeclaration();
178 decls.push_back(std::move(decl));
179 }
180 }
181 }
182 }
183 return decls;
184 }
185
186 std::unique_ptr<ASTNode> PascalParser::parseProcedureForwardDecl() {
187 expectToken("procedure");
188 int lineNum = token->getLine();
189 next();
191 std::string procName = token->getTokenValue();
192 next();
193 std::vector<std::unique_ptr<ASTNode>> parameters;
194 if (peekIs("(")) {
195 next();
196 parameters = parseParameterList();
197 expectToken(")");
198 next();
199 }
200 expectToken(";");
201 next();
202 auto procDeclNode = std::make_unique<ProcDeclNode>(procName, std::move(parameters), nullptr);
203 procDeclNode->setLineNumber(lineNum);
204 return procDeclNode;
205 }
206
207 std::unique_ptr<ASTNode> PascalParser::parseFunctionForwardDecl() {
208 expectToken("function");
209 int lineNum = token->getLine();
210 next();
212 std::string funcName = token->getTokenValue();
213 next();
214 std::vector<std::unique_ptr<ASTNode>> parameters;
215 if (peekIs("(")) {
216 next();
217 parameters = parseParameterList();
218 expectToken(")");
219 next();
220 }
221 expectToken(":");
222 next();
223 std::string returnType;
224 if (peekIs("^")) {
225 next();
227 returnType = "^" + token->getTokenValue();
228 next();
229 } else {
231 returnType = token->getTokenValue();
232 next();
233 }
234 expectToken(";");
235 next();
236 auto funcDeclNode = std::make_unique<FuncDeclNode>(funcName, std::move(parameters), returnType, nullptr);
237 funcDeclNode->setLineNumber(lineNum);
238 return funcDeclNode;
239 }
240
242 if (peekIs(t)) {
243 next();
244 return true;
245 }
246 return false;
247 }
248
249 std::unique_ptr<BlockNode> PascalParser::parseBlock() {
250 int lineNum = token ? token->getLine() : 1;
251 if (peekIs("label")) {
253 }
254 auto declarations = parseDeclarations();
255 auto compoundStatement = parseCompoundStatement();
256 auto blockNode = std::make_unique<BlockNode>(std::move(declarations), std::move(compoundStatement));
257 blockNode->setLineNumber(lineNum);
258 return blockNode;
259 }
260
261 bool PascalParser::isKeyword(const std::string &tok) {
262 std::string lower = tok;
263 std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
264 return lower == "program" || lower == "var" || lower == "begin" || lower == "end" ||
265 lower == "if" || lower == "then" || lower == "else" || lower == "while" ||
266 lower == "do" || lower == "for" || lower == "to" || lower == "downto" ||
267 lower == "procedure" || lower == "function" || lower == "integer" ||
268 lower == "real" || lower == "boolean" || lower == "string" || lower == "char" ||
269 lower == "true" || lower == "false" || lower == "div" || lower == "mod" ||
270 lower == "and" || lower == "or" || lower == "not" || lower == "in" ||
271 lower == "case" || lower == "of" || lower == "repeat" || lower == "until" ||
272 lower == "array" || lower == "type" || lower == "record" || lower == "exit" || lower == "break" || lower == "continue" ||
273 lower == "nil" || lower == "new" || lower == "dispose" || lower == "pointer" || lower == "uses" ||
274 lower == "unit" || lower == "interface" || lower == "implementation" ||
275 lower == "with" || lower == "goto" || lower == "label" ||
276 lower == "packed" || lower == "set" || lower == "file";
277 }
278
279 std::unique_ptr<ASTNode> PascalParser::parseProcedureDeclaration() {
280 expectToken("procedure");
281 int lineNum = token->getLine();
282 next();
284 std::string procName = token->getTokenValue();
285 next();
286 std::vector<std::unique_ptr<ASTNode>> parameters;
287 if (peekIs("(")) {
288 next();
289 parameters = parseParameterList();
290 expectToken(")");
291 next();
292 }
293 expectToken(";");
294 next();
295 auto block = parseBlock();
296 expectToken(";");
297 next();
298 auto procDeclNode = std::make_unique<ProcDeclNode>(procName, std::move(parameters), std::move(block));
299 procDeclNode->setLineNumber(lineNum);
300 return procDeclNode;
301 }
302
303 std::unique_ptr<ASTNode> PascalParser::parseFunctionDeclaration() {
304 expectToken("function");
305 int lineNum = token->getLine();
306 next();
308 std::string funcName = token->getTokenValue();
309 next();
310
311 std::vector<std::unique_ptr<ASTNode>> parameters;
312 if (peekIs("(")) {
313 next();
314 parameters = parseParameterList();
315 expectToken(")");
316 next();
317 }
318
319 expectToken(":");
320 next();
321
322 std::string returnType;
323 if (peekIs("^")) {
324 next();
326 returnType = "^" + token->getTokenValue();
327 next();
328 } else {
330 returnType = token->getTokenValue();
331 next();
332 }
333
334 expectToken(";");
335 next();
336
337 auto block = parseBlock();
338
339 expectToken(";");
340 next();
341
342 auto funcDeclNode = std::make_unique<FuncDeclNode>(
343 funcName, std::move(parameters), returnType, std::move(block));
344 funcDeclNode->setLineNumber(lineNum);
345 return funcDeclNode;
346 }
347
348 std::vector<std::unique_ptr<ASTNode>> PascalParser::parseParameterList() {
349 std::vector<std::unique_ptr<ASTNode>> parameters;
350 if (!peekIs(")")) {
351 parameters.push_back(parseParameter());
352 while (peekIs(";")) {
353 next();
354 parameters.push_back(parseParameter());
355 }
356 }
357 return parameters;
358 }
359
360 std::unique_ptr<ASTNode> PascalParser::parseParameter() {
361 int lineNum = token ? token->getLine() : 1;
362 bool isVar = false;
363 if (peekIs("var")) {
364 isVar = true;
365 next();
366 }
367
368 std::vector<std::string> identifiers;
370 identifiers.push_back(token->getTokenValue());
371 next();
372 while (peekIs(",")) {
373 next();
375 identifiers.push_back(token->getTokenValue());
376 next();
377 }
378
379 expectToken(":");
380 next();
381
382 std::string typeName;
383 if (peekIs("^")) {
384 next();
386 typeName = "^" + token->getTokenValue();
387 next();
388 } else {
390 typeName = token->getTokenValue();
391 next();
392 }
393
394 auto parameterNode = std::make_unique<ParameterNode>(
395 std::move(identifiers), typeName, isVar);
396 parameterNode->setLineNumber(lineNum);
397 return parameterNode;
398 }
399
400 std::unique_ptr<CompoundStmtNode> PascalParser::parseCompoundStatement() {
401 int lineNum = token ? token->getLine() : 1;
402 expectToken("begin");
403 next();
404 auto statements = parseStatementList();
405 expectToken("end");
406 next();
407 auto compoundNode = std::make_unique<CompoundStmtNode>(std::move(statements));
408 compoundNode->setLineNumber(lineNum);
409 return compoundNode;
410 }
411
412 std::unique_ptr<ASTNode> PascalParser::parseStatement() {
413 if (!token) {
414 auto emptyNode = std::make_unique<EmptyStmtNode>();
415 emptyNode->setLineNumber(1);
416 return emptyNode;
417 }
418 if (peekIs("exit")) {
419 int lineNum = token->getLine();
420 next();
421 std::unique_ptr<ASTNode> expr;
422 if (peekIs("(")) {
423 next();
424 expr = parseExpression();
425 expectToken(")");
426 next();
427 } else if (!peekIs(";")) {
428 expr = parseExpression();
429 }
430 expectToken(";");
431 auto exitNode = std::make_unique<ExitNode>(std::move(expr));
432 exitNode->setLineNumber(lineNum);
433 return exitNode;
434 } else if (peekIs("break")) {
435 int lineNum = token->getLine();
436 next();
437 expectToken(";");
438 auto breakNode = std::make_unique<BreakNode>();
439 breakNode->setLineNumber(lineNum);
440 return breakNode;
441 } else if (peekIs("continue")) {
442 int lineNum = token->getLine();
443 next();
444 expectToken(";");
445 auto continueNode = std::make_unique<ContinueNode>();
446 continueNode->setLineNumber(lineNum);
447 return continueNode;
448 } else if (peekIs("begin")) {
449 return parseCompoundStatement();
450 } else if (peekIs("if")) {
451 return parseIfStatement();
452 } else if (peekIs("while")) {
453 return parseWhileStatement();
454 } else if (peekIs("for")) {
455 return parseForStatement();
456 } else if (peekIs("repeat")) {
457 return parseRepeatStatement();
458 } else if (peekIs("case")) {
459 return parseCaseStatement();
460 } else if (peekIs("with")) {
461 return parseWithStatement();
462 } else if (peekIs("goto")) {
463 return parseGotoStatement();
464 } else if (peekIs(types::TokenType::TT_NUM)) {
465 // Label definition: 100: statement
466 std::string lbl = token->getTokenValue();
467 int lineNum = token->getLine();
468 next();
469 if (peekIs(":")) {
470 next();
471 auto stmt = parseStatement();
472 auto labelNode = std::make_unique<LabelStmtNode>(lbl, std::move(stmt));
473 labelNode->setLineNumber(lineNum);
474 return labelNode;
475 }
476 error("Expected ':' after label number");
477 return nullptr;
478 } else if (peekIs(types::TokenType::TT_ID)) {
479 auto lhs = parseLValue();
480 int lineNum = token ? token->getLine() : 1;
481 if (peekIs(":=")) {
482 next();
483 auto rhs = parseExpression();
484 auto assignmentNode = std::make_unique<AssignmentNode>(std::move(lhs), std::move(rhs));
485 assignmentNode->setLineNumber(lineNum);
486 return assignmentNode;
487 }
488 if (auto varNode = dynamic_cast<VariableNode *>(lhs.get())) {
489 if (peekIs("(")) {
490 return parseProcedureCall(varNode->name);
491 }
492 // Bare identifier as statement = parameterless procedure call
493 auto procCallNode = std::make_unique<ProcCallNode>(varNode->name, std::vector<std::unique_ptr<ASTNode>>{});
494 procCallNode->setLineNumber(lineNum);
495 return procCallNode;
496 }
497 if (auto fieldNode = dynamic_cast<FieldAccessNode *>(lhs.get())) {
498 if (dynamic_cast<VariableNode *>(fieldNode->recordExpr.get())) {
499 if (peekIs("(")) {
500 return parseProcedureCall(fieldNode->fieldName);
501 }
502 // Bare qualified name as statement = parameterless procedure call
503 auto procCallNode = std::make_unique<ProcCallNode>(fieldNode->fieldName, std::vector<std::unique_ptr<ASTNode>>{});
504 procCallNode->setLineNumber(lineNum);
505 return procCallNode;
506 }
507 }
508 error("Invalid statement: expected ':=' for assignment or '(' for procedure call");
509 return nullptr;
510 } else {
511 auto emptyNode = std::make_unique<EmptyStmtNode>();
512 emptyNode->setLineNumber(token ? token->getLine() : 1);
513 return emptyNode;
514 }
515 }
516
517 std::unique_ptr<ASTNode> PascalParser::parseAssignmentOrProcCall() {
519 std::string name = token->getTokenValue();
520 int lineNum = token->getLine();
521 next();
522 if (peekIs(":=")) {
523 next();
524 auto variable = std::make_unique<VariableNode>(name);
525 variable->setLineNumber(lineNum);
526 auto expression = parseExpression();
527 auto assignmentNode = std::make_unique<AssignmentNode>(std::move(variable), std::move(expression));
528 assignmentNode->setLineNumber(lineNum);
529 return assignmentNode;
530 } else {
531 return parseProcedureCall(name);
532 }
533 }
534
535 std::unique_ptr<ASTNode> PascalParser::parseIfStatement() {
536 expectToken("if");
537 int lineNum = token->getLine();
538 next();
539 auto condition = parseExpression();
540 expectToken("then");
541 next();
542 auto thenStatement = parseStatement();
543 std::unique_ptr<ASTNode> elseStatement = nullptr;
544 if (peekIs("else")) {
545 next();
546 elseStatement = parseStatement();
547 }
548 auto ifStmtNode = std::make_unique<IfStmtNode>(std::move(condition), std::move(thenStatement), std::move(elseStatement));
549 ifStmtNode->setLineNumber(lineNum);
550 return ifStmtNode;
551 }
552
553 std::unique_ptr<ASTNode> PascalParser::parseWhileStatement() {
554 expectToken("while");
555 int lineNum = token->getLine();
556 next();
557 auto condition = parseExpression();
558 expectToken("do");
559 next();
560 auto statement = parseStatement();
561 auto whileStmtNode = std::make_unique<WhileStmtNode>(std::move(condition), std::move(statement));
562 whileStmtNode->setLineNumber(lineNum);
563 return whileStmtNode;
564 }
565
566 std::unique_ptr<ASTNode> PascalParser::parseForStatement() {
567 expectToken("for");
568 int lineNum = token->getLine();
569 next();
571 std::string variable = token->getTokenValue();
572 next();
573 expectToken(":=");
574 next();
575 auto startValue = parseExpression();
576 bool isDownto = false;
577 if (peekIs("to")) {
578 next();
579 } else if (peekIs("downto")) {
580 isDownto = true;
581 next();
582 } else {
583 error("Expected 'to' or 'downto' in for loop");
584 }
585 auto endValue = parseExpression();
586 expectToken("do");
587 next();
588 auto statement = parseStatement();
589 auto forStmtNode = std::make_unique<ForStmtNode>(variable, std::move(startValue), std::move(endValue), isDownto, std::move(statement));
590 forStmtNode->setLineNumber(lineNum);
591 return forStmtNode;
592 }
593
594 std::unique_ptr<ASTNode> PascalParser::parseRepeatStatement() {
595 expectToken("repeat");
596 int lineNum = token->getLine();
597 next();
598 std::vector<std::unique_ptr<ASTNode>> statements;
599 while (!peekIs("until")) {
600 statements.push_back(parseStatement());
601 if (peekIs(";")) {
602 next();
603 } else if (!peekIs("until")) {
604 error("Expected ';' or 'until'");
605 }
606 }
607 expectToken("until");
608 next();
609 auto condition = parseExpression();
610 auto repeatStmtNode = std::make_unique<RepeatStmtNode>(std::move(statements), std::move(condition));
611 repeatStmtNode->setLineNumber(lineNum);
612 return repeatStmtNode;
613 }
614
615 std::unique_ptr<ASTNode> PascalParser::parseExpression() {
616 int lineNum = token ? token->getLine() : 1;
617 auto left = parseSimpleExpression();
618 if (isRelationalOperator()) {
619 if (peekIs("in")) {
620 next();
621 // Allow both set literal [1,2,3] and set variable
622 auto right = parseSimpleExpression();
623 left = std::make_unique<BinaryOpNode>(std::move(left), BinaryOpNode::IN, std::move(right));
624 left->setLineNumber(lineNum);
625 } else {
626 std::string op = getRelationalOp();
627 next();
628 auto right = parseSimpleExpression();
630 if (op == "=")
631 enumOp = BinaryOpNode::EQUAL;
632 else if (op == "<>")
634 else if (op == "<")
635 enumOp = BinaryOpNode::LESS;
636 else if (op == "<=")
638 else if (op == ">")
639 enumOp = BinaryOpNode::GREATER;
640 else if (op == ">=")
642 left = std::make_unique<BinaryOpNode>(std::move(left), enumOp, std::move(right));
643 left->setLineNumber(lineNum);
644 }
645 }
646 while (peekIs("and") || peekIs("or")) {
648 if (peekIs("and")) {
650 next();
651 } else {
652 op = BinaryOpNode::OR;
653 next();
654 }
655 auto right = parseSimpleExpression();
656 left = std::make_unique<BinaryOpNode>(std::move(left), op, std::move(right));
657 left->setLineNumber(lineNum);
658 }
659 return left;
660 }
661
662 std::unique_ptr<ASTNode> PascalParser::parseSimpleExpression() {
663 std::unique_ptr<ASTNode> result;
664 int lineNum = token ? token->getLine() : 1;
665 if (((peekIs("+") || peekIs("-")) && peekIs(types::TokenType::TT_SYM)) || peekIs("not")) {
667 if (peekIs("+"))
669 else if (peekIs("-"))
671 else if (peekIs("not"))
672 op = UnaryOpNode::NOT;
673 next();
674 auto operand = parseTerm();
675 result = std::make_unique<UnaryOpNode>(op, std::move(operand));
676 result->setLineNumber(lineNum);
677 } else {
678 result = parseTerm();
679 }
680 while ((peekIs("+") || peekIs("-")) && peekIs(types::TokenType::TT_SYM)) {
682 if (peekIs("+"))
684 else
686 next();
687 auto right = parseTerm();
688 result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
689 result->setLineNumber(lineNum);
690 }
691 return result;
692 }
693
694 std::unique_ptr<ASTNode> PascalParser::parseTerm() {
695 int lineNum = token ? token->getLine() : 1;
696 auto result = parseFactor();
697 while (isMulOperator()) {
699 if (peekIs("*"))
701 else if (peekIs("/"))
703 else if (peekIs("div"))
705 else if (peekIs("mod"))
707 next();
708 auto right = parseFactor();
709 result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
710 result->setLineNumber(lineNum);
711 }
712 return result;
713 }
714
715 std::unique_ptr<ASTNode> PascalParser::parseFactor() {
716 int lineNum = token ? token->getLine() : 1;
718 std::string value = token->getTokenValue();
719 next();
720 bool isReal = value.find('.') != std::string::npos || value.find('e') != std::string::npos || value.find('E') != std::string::npos;
721 auto numberNode = std::make_unique<NumberNode>(value, !isReal, isReal);
722 numberNode->setLineNumber(lineNum);
723 return numberNode;
724 } else if (peekIs(types::TokenType::TT_STR)) {
725 std::string value = token->getTokenValue();
726 next();
727 auto stringNode = std::make_unique<StringNode>(value);
728 stringNode->setLineNumber(lineNum);
729 return stringNode;
730 } else if (peekIs("true") || peekIs("false")) {
731 bool value = (token->getTokenValue() == "true");
732 next();
733 auto booleanNode = std::make_unique<BooleanNode>(value);
734 booleanNode->setLineNumber(lineNum);
735 return booleanNode;
736 } else if (peekIs("nil")) {
737 next();
738 auto nilNode = std::make_unique<NilNode>();
739 nilNode->setLineNumber(lineNum);
740 return nilNode;
741 } else if (peekIs("@")) {
742 next();
743 auto operand = parseFactor();
744 auto addrNode = std::make_unique<AddressOfNode>(std::move(operand));
745 addrNode->setLineNumber(lineNum);
746 return addrNode;
747 } else if (peekIs("[")) {
748 // Set constructor: [elem1, elem2, ...]
749 next(); // consume '['
750 std::vector<std::unique_ptr<ASTNode>> elements;
751 if (!peekIs("]")) {
752 elements.push_back(parseExpression());
753 while (peekIs(",")) {
754 next();
755 elements.push_back(parseExpression());
756 }
757 }
758 expectToken("]");
759 next();
760 auto setNode = std::make_unique<SetLiteralNode>(std::move(elements));
761 setNode->setLineNumber(lineNum);
762 return setNode;
763 } else if (peekIs("(")) {
764 next();
765 auto expr = parseExpression();
766 expectToken(")");
767 next();
768 return expr;
769 } else if (peekIs(types::TokenType::TT_ID)) {
770 std::string name = token->getTokenValue();
771 next();
772 std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
773 left->setLineNumber(lineNum);
774 while (true) {
775 if (peekIs("[")) {
776 next();
777 auto index = parseExpression();
778 expectToken("]");
779 next();
780 left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(index));
781 left->setLineNumber(lineNum);
782 } else if (peekIs(".")) {
783 next();
785 std::string fieldName = token->getTokenValue();
786 next();
787 left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
788 left->setLineNumber(lineNum);
789 } else if (peekIs("^")) {
790 next();
791 left = std::make_unique<PointerDerefNode>(std::move(left));
792 left->setLineNumber(lineNum);
793 } else if (peekIs("(")) {
794 if (auto varNode = dynamic_cast<VariableNode *>(left.get())) {
795 return parseFunctionCall(varNode->name);
796 } else if (auto fieldNode = dynamic_cast<FieldAccessNode *>(left.get())) {
797 if (dynamic_cast<VariableNode *>(fieldNode->recordExpr.get())) {
798 return parseFunctionCall(fieldNode->fieldName);
799 }
800 error("Function call must be on a simple or qualified identifier");
801 } else {
802 error("Function call must be on a simple identifier");
803 }
804 } else {
805 break;
806 }
807 }
808 return left;
809 } else {
810 error("Expected factor");
811 return nullptr;
812 }
813 }
814
815 std::unique_ptr<ASTNode> PascalParser::parseProcedureCall(const std::string &name) {
816 int lineNum = token ? token->getLine() : 1;
817 std::vector<std::unique_ptr<ASTNode>> arguments;
818 if (peekIs("(")) {
819 next();
820 arguments = parseArgumentList();
821 expectToken(")");
822 next();
823 }
824 auto procCallNode = std::make_unique<ProcCallNode>(name, std::move(arguments));
825 procCallNode->setLineNumber(lineNum);
826 return procCallNode;
827 }
828
829 std::unique_ptr<ASTNode> PascalParser::parseFunctionCall(const std::string &name) {
830 int lineNum = token ? token->getLine() : 1;
831 std::vector<std::unique_ptr<ASTNode>> arguments;
832 expectToken("(");
833 next();
834 arguments = parseArgumentList();
835 expectToken(")");
836 next();
837 auto funcCallNode = std::make_unique<FuncCallNode>(name, std::move(arguments));
838 funcCallNode->setLineNumber(lineNum);
839 return funcCallNode;
840 }
841
842 std::unique_ptr<ASTNode> PascalParser::parseCaseStatement() {
843 expectToken("case");
844 int lineNum = token->getLine();
845 next();
846 auto expression = parseExpression();
847 expectToken("of");
848 next();
849 std::vector<std::unique_ptr<CaseStmtNode::CaseBranch>> branches;
850 while (!peekIs("end") && !peekIs("else")) {
851 std::vector<std::unique_ptr<ASTNode>> values;
852 values.push_back(parseExpression());
853 while (peekIs(",")) {
854 next();
855 values.push_back(parseExpression());
856 }
857 expectToken(":");
858 next();
859 auto statement = parseStatement();
860 branches.push_back(std::make_unique<CaseStmtNode::CaseBranch>(std::move(values), std::move(statement)));
861 if (peekIs(";"))
862 next();
863 }
864 std::unique_ptr<ASTNode> elseStatement = nullptr;
865 if (peekIs("else")) {
866 next();
867 elseStatement = parseStatement();
868 if (peekIs(";"))
869 next();
870 }
871 expectToken("end");
872 next();
873 auto caseStmtNode = std::make_unique<CaseStmtNode>(std::move(expression), std::move(branches), std::move(elseStatement));
874 caseStmtNode->setLineNumber(lineNum);
875 return caseStmtNode;
876 }
877
878 std::unique_ptr<ASTNode> PascalParser::parseConstDeclaration() {
879 expectToken("const");
880 int lineNum = token->getLine();
881 next();
882 std::vector<std::unique_ptr<ConstDeclNode::ConstAssignment>> assignments;
883 do {
885 std::string identifier = token->getTokenValue();
886 next();
887 expectToken("=");
888 next();
889 auto value = parseExpression();
890 assignments.push_back(std::make_unique<ConstDeclNode::ConstAssignment>(identifier, std::move(value)));
891 expectToken(";");
892 next();
893 } while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue()));
894 auto constDeclNode = std::make_unique<ConstDeclNode>(std::move(assignments));
895 constDeclNode->setLineNumber(lineNum);
896 return constDeclNode;
897 }
898
899 std::vector<std::unique_ptr<ASTNode>> PascalParser::parseDeclarations() {
900 std::vector<std::unique_ptr<ASTNode>> declarations;
901 while (peekIs("type") || peekIs("const") || peekIs("var") || peekIs("procedure") || peekIs("function") || peekIs("label")) {
902 if (peekIs("label")) {
904 } else if (peekIs("type")) {
905 declarations.push_back(parseTypeDeclaration());
906 } else if (peekIs("const")) {
907 declarations.push_back(parseConstDeclaration());
908 } else if (peekIs("var")) {
909 if (match("var")) {
910 while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue())) {
911 auto decl = parseVarDeclaration();
912 declarations.push_back(std::move(decl));
913 }
914 }
915 } else if (peekIs("procedure")) {
916 declarations.push_back(parseProcedureDeclaration());
917 } else if (peekIs("function")) {
918 declarations.push_back(parseFunctionDeclaration());
919 }
920 }
921 return declarations;
922 }
923
924 std::vector<std::unique_ptr<ASTNode>> PascalParser::parseStatementList() {
925 std::vector<std::unique_ptr<ASTNode>> statements;
926 while (!peekIs("end") && !peekIs("else") && !peekIs("until")) {
927 statements.push_back(parseStatement());
928 if (peekIs(";")) {
929 next();
930 if (peekIs("end") || peekIs("else") || peekIs("until"))
931 break;
932 } else {
933 break;
934 }
935 }
936 return statements;
937 }
938
939 std::vector<std::unique_ptr<ASTNode>> PascalParser::parseArgumentList() {
940 std::vector<std::unique_ptr<ASTNode>> arguments;
941 if (!peekIs(")")) {
942 arguments.push_back(parseExpression());
943 while (peekIs(",")) {
944 next();
945 arguments.push_back(parseExpression());
946 }
947 }
948 return arguments;
949 }
950
953 return false;
954 return peekIs("*") || peekIs("/") || peekIs("div") || peekIs("mod");
955 }
956
958 if (peekIs("in"))
959 return true;
961 return false;
962 return peekIs("=") || peekIs("<>") || peekIs("<") || peekIs("<=") || peekIs(">") || peekIs(">=");
963 }
964
966 if (peekIs("in"))
967 return "in";
968 if (peekIs("="))
969 return "=";
970 if (peekIs("<>"))
971 return "<>";
972 if (peekIs("<="))
973 return "<=";
974 if (peekIs(">="))
975 return ">=";
976 if (peekIs("<"))
977 return "<";
978 if (peekIs(">"))
979 return ">";
980 error("Invalid relational operator");
981 return "";
982 }
983
984 std::unique_ptr<ASTNode> PascalParser::parseTypeDeclaration() {
985 expectToken("type");
986 int lineNum = token->getLine();
987 next();
988
989 std::vector<std::unique_ptr<ASTNode>> typeDeclarations;
990
991 do {
993 std::string typeName = token->getTokenValue();
994 next();
995 expectToken("=");
996 next();
997
998 std::unique_ptr<ASTNode> typeDefinition;
999 //bool isPacked = false;
1000 if (peekIs("packed")) {
1001 // isPacked = true;
1002 next(); // consume 'packed' modifier (accepted but has no effect)
1003 }
1004 if (peekIs("record")) {
1005 auto recordType = parseRecordType();
1006 typeDefinition = std::make_unique<RecordDeclarationNode>(
1007 typeName,
1008 std::unique_ptr<RecordTypeNode>(static_cast<RecordTypeNode *>(recordType.release())));
1009 } else if (peekIs("(")) {
1010 // Enumerated type: Color = (Red, Green, Blue)
1011 next(); // consume '('
1012 std::vector<std::string> enumValues;
1014 enumValues.push_back(token->getTokenValue());
1015 next();
1016 while (peekIs(",")) {
1017 next();
1019 enumValues.push_back(token->getTokenValue());
1020 next();
1021 }
1022 expectToken(")");
1023 next();
1024 typeDefinition = std::make_unique<EnumTypeDeclNode>(typeName, std::move(enumValues));
1025 } else if (peekIs("array")) {
1026 auto arrayType = parseArrayType();
1027 typeDefinition = std::make_unique<ArrayTypeDeclarationNode>(
1028 typeName,
1029 std::unique_ptr<ArrayTypeNode>(static_cast<ArrayTypeNode *>(arrayType.release())));
1030 } else if (peekIs("set")) {
1031 next(); // consume 'set'
1032 expectToken("of");
1033 next();
1035 std::string baseType = token->getTokenValue();
1036 next();
1037 typeDefinition = std::make_unique<TypeAliasNode>(typeName, "set of " + baseType);
1038 } else if (peekIs("file")) {
1039 next(); // consume 'file'
1040 if (peekIs("of")) {
1041 next(); // consume 'of'
1043 next(); // consume element type (ignored — all files are byte-stream)
1044 }
1045 typeDefinition = std::make_unique<TypeAliasNode>(typeName, "file");
1046 } else if (peekIs("^")) {
1047 next();
1049 std::string baseType = token->getTokenValue();
1050 next();
1051 typeDefinition = std::make_unique<TypeAliasNode>(typeName, "^" + baseType);
1052 } else {
1054 std::string baseType = token->getTokenValue();
1055 next();
1056 typeDefinition = std::make_unique<TypeAliasNode>(typeName, baseType);
1057 }
1058
1059 expectToken(";");
1060 next();
1061
1062 typeDeclarations.push_back(std::move(typeDefinition));
1063 } while (peekIs(types::TokenType::TT_ID) && !isKeyword(token->getTokenValue()));
1064
1065 auto typeDeclNode = std::make_unique<TypeDeclNode>(std::move(typeDeclarations));
1066 typeDeclNode->setLineNumber(lineNum);
1067 return typeDeclNode;
1068 }
1069
1070 std::unique_ptr<ASTNode> PascalParser::parseRecordType() {
1071 expectToken("record");
1072 next();
1073 std::vector<std::unique_ptr<ASTNode>> fields;
1074 while (!peekIs("end") && !peekIs("case")) {
1075 std::vector<std::string> ids;
1077 ids.push_back(token->getTokenValue());
1078 next();
1079 while (peekIs(",")) {
1080 next();
1082 ids.push_back(token->getTokenValue());
1083 next();
1084 }
1085 expectToken(":");
1086 next();
1087 auto fieldType = parseTypeSpec();
1088 fields.push_back(std::make_unique<VarDeclNode>(
1089 std::move(ids),
1090 std::move(fieldType),
1091 std::vector<std::unique_ptr<ASTNode>>{}));
1092 expectToken(";");
1093 next();
1094 }
1095
1096 auto recordNode = std::make_unique<RecordTypeNode>(std::move(fields));
1097
1098 // Parse variant part: case tag: type of ...
1099 if (peekIs("case")) {
1100 next(); // consume 'case'
1102 recordNode->variantTagName = token->getTokenValue();
1103 next();
1104 expectToken(":");
1105 next();
1107 recordNode->variantTagType = token->getTokenValue();
1108 next();
1109 expectToken("of");
1110 next();
1111
1112 while (!peekIs("end")) {
1113 VariantArm arm;
1114 // Parse case label(s): e.g. 1, 2:
1115 arm.caseLabels.push_back(parseExpression());
1116 while (peekIs(",")) {
1117 next();
1118 arm.caseLabels.push_back(parseExpression());
1119 }
1120 expectToken(":");
1121 next();
1122 expectToken("(");
1123 next();
1124 // Parse fields inside parentheses
1125 while (!peekIs(")")) {
1126 std::vector<std::string> ids;
1128 ids.push_back(token->getTokenValue());
1129 next();
1130 while (peekIs(",")) {
1131 next();
1133 ids.push_back(token->getTokenValue());
1134 next();
1135 }
1136 expectToken(":");
1137 next();
1138 auto fieldType = parseTypeSpec();
1139 arm.fields.push_back(std::make_unique<VarDeclNode>(
1140 std::move(ids),
1141 std::move(fieldType),
1142 std::vector<std::unique_ptr<ASTNode>>{}));
1143 if (peekIs(";"))
1144 next();
1145 }
1146 expectToken(")");
1147 next();
1148 if (peekIs(";"))
1149 next();
1150 recordNode->variantArms.push_back(std::move(arm));
1151 }
1152 }
1153
1154 expectToken("end");
1155 next();
1156 return recordNode;
1157 }
1158
1159 std::unique_ptr<ASTNode> PascalParser::parseVarDeclaration() {
1160 std::vector<std::string> identifiers;
1161 std::vector<std::unique_ptr<ASTNode>> initializers;
1162
1163 do {
1165 identifiers.push_back(token->getTokenValue());
1166 next();
1167 if (peekIs(","))
1168 next();
1169 else
1170 break;
1171 } while (true);
1172
1173 expectToken(":");
1174 next();
1175
1176 auto typeAst = parseTypeSpec();
1177
1178 if (peekIs(":=")) {
1179 next();
1180 initializers.push_back(parseExpression());
1181 }
1182
1183 expectToken(";");
1184 next();
1185
1186 return std::make_unique<VarDeclNode>(
1187 std::move(identifiers),
1188 std::move(typeAst),
1189 std::move(initializers));
1190 }
1191
1192 std::unique_ptr<ASTNode> PascalParser::parseTypeSpec() {
1193 if (peekIs("packed"))
1194 next(); // consume 'packed' modifier (accepted but has no effect)
1195 if (peekIs("set")) {
1196 next(); // consume 'set'
1197 expectToken("of");
1198 next();
1200 std::string baseType = token->getTokenValue();
1201 next();
1202 return std::make_unique<SetTypeNode>(baseType);
1203 }
1204 if (peekIs("file")) {
1205 next(); // consume 'file'
1206 if (peekIs("of")) {
1207 next(); // consume 'of' (element type accepted but treated as untyped)
1209 next(); // consume element type (ignored — all files are byte-stream)
1210 }
1211 return std::make_unique<SimpleTypeNode>("file");
1212 }
1213 if (peekIs("array"))
1214 return parseArrayType();
1215 if (peekIs("record"))
1216 return parseRecordType();
1217 if (peekIs("^")) {
1218 next();
1220 std::string baseType = token->getTokenValue();
1221 next();
1222 return std::make_unique<PointerTypeNode>(baseType);
1223 }
1225 auto t = std::make_unique<SimpleTypeNode>(token->getTokenValue());
1226 next();
1227 return t;
1228 }
1229
1230 std::unique_ptr<ASTNode> PascalParser::parseArrayType() {
1231 expectToken("array");
1232 next();
1233 // Dynamic array: array of <type> (no bounds)
1234 if (peekIs("of")) {
1235 next();
1236 auto elementType = parseTypeSpec();
1237 return std::make_unique<ArrayTypeNode>(
1238 std::move(elementType),
1239 nullptr,
1240 nullptr);
1241 }
1242 // Static array: array[lo..hi] of <type>
1243 expectToken("[");
1244 next();
1245 auto lowerBound = parseExpression();
1246 expectToken("..");
1247 next();
1248 auto upperBound = parseExpression();
1249 expectToken("]");
1250 next();
1251 expectToken("of");
1252 next();
1253 auto elementType = parseTypeSpec();
1254 return std::make_unique<ArrayTypeNode>(
1255 std::move(elementType),
1256 std::move(lowerBound),
1257 std::move(upperBound));
1258 }
1259
1261 switch (type) {
1263 return "identifier";
1265 return "number";
1267 return "string";
1269 return "symbol";
1270 default:
1271 return "unknown token";
1272 }
1273 }
1274
1275 std::unique_ptr<ASTNode> PascalParser::parseLValue() {
1276 int lineNum = token ? token->getLine() : 1;
1278 std::string name = token->getTokenValue();
1279 next();
1280
1281 std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
1282 left->setLineNumber(lineNum);
1283
1284 while (true) {
1285 if (peekIs("[")) {
1286 next();
1287 auto index = parseExpression();
1288 expectToken("]");
1289 next();
1290 left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(index));
1291 left->setLineNumber(lineNum);
1292 } else if (peekIs(".")) {
1293 next();
1295 std::string fieldName = token->getTokenValue();
1296 next();
1297 left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
1298 left->setLineNumber(lineNum);
1299 } else if (peekIs("^")) {
1300 next();
1301 left = std::make_unique<PointerDerefNode>(std::move(left));
1302 left->setLineNumber(lineNum);
1303 } else {
1304 break;
1305 }
1306 }
1307 return left;
1308 }
1309
1310 std::unique_ptr<ASTNode> PascalParser::parseWithStatement() {
1311 expectToken("with");
1312 int lineNum = token->getLine();
1313 next();
1315 std::string recordVar = token->getTokenValue();
1316 next();
1317 expectToken("do");
1318 next();
1319 auto stmt = parseStatement();
1320 auto withNode = std::make_unique<WithStmtNode>(recordVar, std::move(stmt));
1321 withNode->setLineNumber(lineNum);
1322 return withNode;
1323 }
1324
1325 std::unique_ptr<ASTNode> PascalParser::parseGotoStatement() {
1326 expectToken("goto");
1327 int lineNum = token->getLine();
1328 next();
1330 std::string label = token->getTokenValue();
1331 next();
1332 auto gotoNode = std::make_unique<GotoStmtNode>(label);
1333 gotoNode->setLineNumber(lineNum);
1334 return gotoNode;
1335 }
1336
1338 expectToken("label");
1339 next();
1340 do {
1342 declaredLabels.insert(token->getTokenValue());
1343 next();
1344 if (peekIs(",")) {
1345 next();
1346 } else {
1347 break;
1348 }
1349 } while (true);
1350 expectToken(";");
1351 next();
1352 }
1353
1354} // namespace pascal
scan::TToken * token
current token pointer
Definition parser.hpp:100
scan::Scanner scanner
underlying scanner
Definition parser.hpp:99
bool peekIs(const std::string &s)
Check if the current token's value matches a string (case-insensitive).
Definition parser.hpp:61
size_t index
current token index
Definition parser.hpp:101
bool next()
Advance to the next token; returns false at end of stream.
Definition parser.hpp:50
AST node for an array type (array[lower..upper] of elementType).
Definition ast.hpp:275
OpType
Binary operator kinds.
Definition ast.hpp:441
AST node for accessing a record field (record.field).
Definition ast.hpp:726
Exception thrown on parse errors.
Definition parser.hpp:18
std::unique_ptr< ASTNode > parseWithStatement()
Parse a with statement.
Definition parser.cpp:1310
bool match(const std::string &s)
Try to match and consume a token by value.
Definition parser.cpp:79
std::unique_ptr< ASTNode > parseTypeDeclaration()
Parse a type declaration section.
Definition parser.cpp:984
std::vector< std::unique_ptr< ASTNode > > parseStatementList()
Parse a list of statements (separated by semicolons).
Definition parser.cpp:924
void error(const std::string &message)
Report a parse error with the given message.
Definition parser.cpp:33
std::unique_ptr< ASTNode > parseVarDeclaration()
Parse a var declaration section.
Definition parser.cpp:1159
std::unique_ptr< ASTNode > parseExpression()
Parse a full expression (simple expression with optional relational op).
Definition parser.cpp:615
std::unique_ptr< ASTNode > parseGotoStatement()
Parse a goto statement.
Definition parser.cpp:1325
std::unique_ptr< ASTNode > parseProcedureDeclaration()
Parse a procedure declaration.
Definition parser.cpp:279
std::unique_ptr< ASTNode > parseParameter()
Parse a single formal parameter.
Definition parser.cpp:360
std::unique_ptr< ASTNode > parseTypeSpec()
Parse a type specifier.
Definition parser.cpp:1192
void expectToken(const std::string &expected)
Consume a token matching the expected string, or throw.
Definition parser.cpp:37
void parseLabelDeclaration()
Parse a label declaration section (label 100, 200;).
Definition parser.cpp:1337
std::unique_ptr< ProgramNode > parseProgram()
Parse a complete Pascal program and return the root AST node.
Definition parser.cpp:47
bool isKeyword(const std::string &s)
Check if a string is a reserved keyword.
Definition parser.cpp:261
std::unique_ptr< ASTNode > parseRecordType()
Parse a record type definition.
Definition parser.cpp:1070
std::unique_ptr< ASTNode > parseForStatement()
Parse a for-to/downto-do statement.
Definition parser.cpp:566
std::unique_ptr< ASTNode > parseIfStatement()
Parse an if-then-else statement.
Definition parser.cpp:535
std::unique_ptr< ASTNode > parseSimpleExpression()
Parse a simple expression (terms combined by +, -, or).
Definition parser.cpp:662
std::unique_ptr< ASTNode > parseConstDeclaration()
Parse a const declaration section.
Definition parser.cpp:878
std::vector< std::unique_ptr< ASTNode > > parseParameterList()
Parse a formal parameter list.
Definition parser.cpp:348
std::unique_ptr< ASTNode > parseAssignmentOrProcCall()
Parse an assignment or procedure call starting with an identifier.
Definition parser.cpp:517
std::unique_ptr< BlockNode > parseBlock()
Parse a block (declarations + compound statement).
Definition parser.cpp:249
std::unique_ptr< UnitNode > parseUnit()
Parse a Pascal unit and return the root AST node.
Definition parser.cpp:95
std::unique_ptr< ASTNode > parseProcedureForwardDecl()
Parse a procedure forward declaration (signature only, no body).
Definition parser.cpp:186
std::unordered_set< std::string > declaredLabels
Set of user-declared goto labels.
Definition parser.hpp:203
std::vector< std::unique_ptr< ASTNode > > parseArgumentList()
Parse a comma-separated argument list.
Definition parser.cpp:939
bool isUnitSource() const
Check if the source starts with a 'unit' keyword.
Definition parser.cpp:87
bool isMulOperator()
Check if current token is a multiplicative operator.
Definition parser.cpp:951
std::vector< std::unique_ptr< ASTNode > > parseInterfaceDeclarations()
Parse interface forward declarations (procedure/function signatures only).
Definition parser.cpp:163
std::string tokenTypeToString(types::TokenType type)
Convert a TokenType to its display string.
Definition parser.cpp:1260
std::unique_ptr< ASTNode > parseFunctionDeclaration()
Parse a function declaration.
Definition parser.cpp:303
std::vector< std::unique_ptr< ASTNode > > parseDeclarations()
Parse the declarations section.
Definition parser.cpp:899
std::unique_ptr< ASTNode > parseFunctionForwardDecl()
Parse a function forward declaration (signature only, no body).
Definition parser.cpp:207
std::unique_ptr< ASTNode > parseFunctionCall(const std::string &name)
Parse a function call given its already-parsed name.
Definition parser.cpp:829
void removeBraceComments()
Remove {brace} comments from the token stream.
Definition parser.cpp:12
std::unique_ptr< ASTNode > parseArrayType()
Parse an array type specification.
Definition parser.cpp:1230
std::unique_ptr< ASTNode > parseCaseStatement()
Parse a case statement.
Definition parser.cpp:842
std::unique_ptr< ASTNode > parseLValue()
Parse an lvalue (variable, array access, pointer deref, field access).
Definition parser.cpp:1275
std::unique_ptr< ASTNode > parseProcedureCall(const std::string &name)
Parse a procedure call given its already-parsed name.
Definition parser.cpp:815
std::unique_ptr< ASTNode > parseFactor()
Parse a factor (literal, variable, function call, sub-expression).
Definition parser.cpp:715
std::unique_ptr< ASTNode > parseWhileStatement()
Parse a while-do statement.
Definition parser.cpp:553
std::unique_ptr< ASTNode > parseTerm()
Parse a term (factors combined by *, /, div, mod, and).
Definition parser.cpp:694
std::unique_ptr< ASTNode > parseRepeatStatement()
Parse a repeat-until statement.
Definition parser.cpp:594
std::string getRelationalOp()
Consume and return a relational operator string.
Definition parser.cpp:965
std::unique_ptr< CompoundStmtNode > parseCompoundStatement()
Parse a compound statement (begin..end).
Definition parser.cpp:400
std::unique_ptr< ASTNode > parseStatement()
Parse a single statement.
Definition parser.cpp:412
bool isRelationalOperator()
Check if current token is a relational operator.
Definition parser.cpp:957
AST node for a record type (record ... end).
Definition ast.hpp:646
Operator
Unary operator kinds.
Definition ast.hpp:480
@ NOT
logical not
Definition ast.hpp:483
@ MINUS
unary -
Definition ast.hpp:482
@ PLUS
unary +
Definition ast.hpp:481
AST node for a variable reference.
Definition ast.hpp:513
Definition ast.cpp:9
TokenType
Classification of scanned tokens.
Definition types.hpp:16
@ TT_SYM
symbol / operator token
Definition types.hpp:19
@ TT_STR
string literal
Definition types.hpp:20
@ TT_ID
identifier or keyword
Definition types.hpp:17
@ TT_NUM
decimal numeric literal
Definition types.hpp:21
Pascal recursive-descent parser producing a Pascal AST.
A single variant arm inside a variant record.
Definition ast.hpp:640
std::vector< std::unique_ptr< ASTNode > > fields
field declarations in this arm
Definition ast.hpp:642
std::vector< std::unique_ptr< ASTNode > > caseLabels
case constant(s) for this arm
Definition ast.hpp:641