13 auto &toks =
scanner.getTokens();
14 for (
size_t i = 0; i < toks.size();) {
15 if (toks[i].getTokenValue() ==
"{") {
18 while (i < toks.size() && toks[i].getTokenValue() !=
"}") {
21 if (i < toks.size()) {
24 toks.erase(toks.begin() +
static_cast<int64_t
>(start),
25 toks.begin() +
static_cast<int64_t
>(i));
34 throw ParseException(
"Parse error: " + message + (
token ?
" at '" +
token->getTokenValue() +
"'" :
" at end of input"));
39 error(
"Expected '" + expected +
"'" +
" on Line: " + std::to_string(
token->getLine()));
49 int lineNum =
token->getLine();
52 std::string programName =
token->getTokenValue();
56 std::vector<std::string> usesList;
60 usesList.push_back(
token->getTokenValue());
65 usesList.push_back(
token->getTokenValue());
73 auto programNode = std::make_unique<ProgramNode>(programName, std::move(block));
74 programNode->uses = std::move(usesList);
75 programNode->setLineNumber(lineNum);
90 std::string val =
token->getTokenValue();
91 std::transform(val.begin(), val.end(), val.begin(), ::tolower);
97 int lineNum =
token->getLine();
100 std::string unitName =
token->getTokenValue();
105 auto unitNode = std::make_unique<UnitNode>(unitName);
106 unitNode->setLineNumber(lineNum);
113 std::vector<std::string> usesList;
117 usesList.push_back(
token->getTokenValue());
122 usesList.push_back(
token->getTokenValue());
128 unitNode->uses = std::move(usesList);
141 unitNode->uses.push_back(
token->getTokenValue());
146 unitNode->uses.push_back(
token->getTokenValue());
164 std::vector<std::unique_ptr<ASTNode>> decls;
166 if (
peekIs(
"procedure")) {
168 }
else if (
peekIs(
"function")) {
170 }
else if (
peekIs(
"type")) {
172 }
else if (
peekIs(
"const")) {
174 }
else if (
peekIs(
"var")) {
178 decls.push_back(std::move(decl));
188 int lineNum =
token->getLine();
191 std::string procName =
token->getTokenValue();
193 std::vector<std::unique_ptr<ASTNode>> parameters;
202 auto procDeclNode = std::make_unique<ProcDeclNode>(procName, std::move(parameters),
nullptr);
203 procDeclNode->setLineNumber(lineNum);
209 int lineNum =
token->getLine();
212 std::string funcName =
token->getTokenValue();
214 std::vector<std::unique_ptr<ASTNode>> parameters;
223 std::string returnType;
227 returnType =
"^" +
token->getTokenValue();
231 returnType =
token->getTokenValue();
236 auto funcDeclNode = std::make_unique<FuncDeclNode>(funcName, std::move(parameters), returnType,
nullptr);
237 funcDeclNode->setLineNumber(lineNum);
256 auto blockNode = std::make_unique<BlockNode>(std::move(declarations), std::move(compoundStatement));
257 blockNode->setLineNumber(lineNum);
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";
281 int lineNum =
token->getLine();
284 std::string procName =
token->getTokenValue();
286 std::vector<std::unique_ptr<ASTNode>> parameters;
298 auto procDeclNode = std::make_unique<ProcDeclNode>(procName, std::move(parameters), std::move(block));
299 procDeclNode->setLineNumber(lineNum);
305 int lineNum =
token->getLine();
308 std::string funcName =
token->getTokenValue();
311 std::vector<std::unique_ptr<ASTNode>> parameters;
322 std::string returnType;
326 returnType =
"^" +
token->getTokenValue();
330 returnType =
token->getTokenValue();
342 auto funcDeclNode = std::make_unique<FuncDeclNode>(
343 funcName, std::move(parameters), returnType, std::move(block));
344 funcDeclNode->setLineNumber(lineNum);
349 std::vector<std::unique_ptr<ASTNode>> parameters;
368 std::vector<std::string> identifiers;
370 identifiers.push_back(
token->getTokenValue());
375 identifiers.push_back(
token->getTokenValue());
382 std::string typeName;
386 typeName =
"^" +
token->getTokenValue();
390 typeName =
token->getTokenValue();
394 auto parameterNode = std::make_unique<ParameterNode>(
395 std::move(identifiers), typeName, isVar);
396 parameterNode->setLineNumber(lineNum);
397 return parameterNode;
407 auto compoundNode = std::make_unique<CompoundStmtNode>(std::move(statements));
408 compoundNode->setLineNumber(lineNum);
414 auto emptyNode = std::make_unique<EmptyStmtNode>();
415 emptyNode->setLineNumber(1);
419 int lineNum =
token->getLine();
421 std::unique_ptr<ASTNode> expr;
427 }
else if (!
peekIs(
";")) {
431 auto exitNode = std::make_unique<ExitNode>(std::move(expr));
432 exitNode->setLineNumber(lineNum);
434 }
else if (
peekIs(
"break")) {
435 int lineNum =
token->getLine();
438 auto breakNode = std::make_unique<BreakNode>();
439 breakNode->setLineNumber(lineNum);
441 }
else if (
peekIs(
"continue")) {
442 int lineNum =
token->getLine();
445 auto continueNode = std::make_unique<ContinueNode>();
446 continueNode->setLineNumber(lineNum);
448 }
else if (
peekIs(
"begin")) {
450 }
else if (
peekIs(
"if")) {
452 }
else if (
peekIs(
"while")) {
454 }
else if (
peekIs(
"for")) {
456 }
else if (
peekIs(
"repeat")) {
458 }
else if (
peekIs(
"case")) {
460 }
else if (
peekIs(
"with")) {
462 }
else if (
peekIs(
"goto")) {
466 std::string lbl =
token->getTokenValue();
467 int lineNum =
token->getLine();
472 auto labelNode = std::make_unique<LabelStmtNode>(lbl, std::move(stmt));
473 labelNode->setLineNumber(lineNum);
476 error(
"Expected ':' after label number");
484 auto assignmentNode = std::make_unique<AssignmentNode>(std::move(lhs), std::move(rhs));
485 assignmentNode->setLineNumber(lineNum);
486 return assignmentNode;
488 if (
auto varNode =
dynamic_cast<VariableNode *
>(lhs.get())) {
493 auto procCallNode = std::make_unique<ProcCallNode>(varNode->name, std::vector<std::unique_ptr<ASTNode>>{});
494 procCallNode->setLineNumber(lineNum);
498 if (
dynamic_cast<VariableNode *
>(fieldNode->recordExpr.get())) {
503 auto procCallNode = std::make_unique<ProcCallNode>(fieldNode->fieldName, std::vector<std::unique_ptr<ASTNode>>{});
504 procCallNode->setLineNumber(lineNum);
508 error(
"Invalid statement: expected ':=' for assignment or '(' for procedure call");
511 auto emptyNode = std::make_unique<EmptyStmtNode>();
512 emptyNode->setLineNumber(
token ?
token->getLine() : 1);
519 std::string name =
token->getTokenValue();
520 int lineNum =
token->getLine();
524 auto variable = std::make_unique<VariableNode>(name);
525 variable->setLineNumber(lineNum);
527 auto assignmentNode = std::make_unique<AssignmentNode>(std::move(variable), std::move(expression));
528 assignmentNode->setLineNumber(lineNum);
529 return assignmentNode;
537 int lineNum =
token->getLine();
543 std::unique_ptr<ASTNode> elseStatement =
nullptr;
548 auto ifStmtNode = std::make_unique<IfStmtNode>(std::move(condition), std::move(thenStatement), std::move(elseStatement));
549 ifStmtNode->setLineNumber(lineNum);
555 int lineNum =
token->getLine();
561 auto whileStmtNode = std::make_unique<WhileStmtNode>(std::move(condition), std::move(statement));
562 whileStmtNode->setLineNumber(lineNum);
563 return whileStmtNode;
568 int lineNum =
token->getLine();
571 std::string variable =
token->getTokenValue();
576 bool isDownto =
false;
579 }
else if (
peekIs(
"downto")) {
583 error(
"Expected 'to' or 'downto' in for loop");
589 auto forStmtNode = std::make_unique<ForStmtNode>(variable, std::move(startValue), std::move(endValue), isDownto, std::move(statement));
590 forStmtNode->setLineNumber(lineNum);
596 int lineNum =
token->getLine();
598 std::vector<std::unique_ptr<ASTNode>> statements;
599 while (!
peekIs(
"until")) {
603 }
else if (!
peekIs(
"until")) {
604 error(
"Expected ';' or 'until'");
610 auto repeatStmtNode = std::make_unique<RepeatStmtNode>(std::move(statements), std::move(condition));
611 repeatStmtNode->setLineNumber(lineNum);
612 return repeatStmtNode;
623 left = std::make_unique<BinaryOpNode>(std::move(left),
BinaryOpNode::IN, std::move(right));
624 left->setLineNumber(lineNum);
642 left = std::make_unique<BinaryOpNode>(std::move(left), enumOp, std::move(right));
643 left->setLineNumber(lineNum);
656 left = std::make_unique<BinaryOpNode>(std::move(left), op, std::move(right));
657 left->setLineNumber(lineNum);
663 std::unique_ptr<ASTNode> result;
675 result = std::make_unique<UnaryOpNode>(op, std::move(operand));
676 result->setLineNumber(lineNum);
688 result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
689 result->setLineNumber(lineNum);
709 result = std::make_unique<BinaryOpNode>(std::move(result), op, std::move(right));
710 result->setLineNumber(lineNum);
718 std::string value =
token->getTokenValue();
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);
725 std::string value =
token->getTokenValue();
727 auto stringNode = std::make_unique<StringNode>(value);
728 stringNode->setLineNumber(lineNum);
731 bool value = (
token->getTokenValue() ==
"true");
733 auto booleanNode = std::make_unique<BooleanNode>(value);
734 booleanNode->setLineNumber(lineNum);
736 }
else if (
peekIs(
"nil")) {
738 auto nilNode = std::make_unique<NilNode>();
739 nilNode->setLineNumber(lineNum);
744 auto addrNode = std::make_unique<AddressOfNode>(std::move(operand));
745 addrNode->setLineNumber(lineNum);
750 std::vector<std::unique_ptr<ASTNode>> elements;
760 auto setNode = std::make_unique<SetLiteralNode>(std::move(elements));
761 setNode->setLineNumber(lineNum);
770 std::string name =
token->getTokenValue();
772 std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
773 left->setLineNumber(lineNum);
780 left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(
index));
781 left->setLineNumber(lineNum);
785 std::string fieldName =
token->getTokenValue();
787 left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
788 left->setLineNumber(lineNum);
791 left = std::make_unique<PointerDerefNode>(std::move(left));
792 left->setLineNumber(lineNum);
794 if (
auto varNode =
dynamic_cast<VariableNode *
>(left.get())) {
796 }
else if (
auto fieldNode =
dynamic_cast<FieldAccessNode *
>(left.get())) {
797 if (
dynamic_cast<VariableNode *
>(fieldNode->recordExpr.get())) {
800 error(
"Function call must be on a simple or qualified identifier");
802 error(
"Function call must be on a simple identifier");
810 error(
"Expected factor");
817 std::vector<std::unique_ptr<ASTNode>> arguments;
824 auto procCallNode = std::make_unique<ProcCallNode>(name, std::move(arguments));
825 procCallNode->setLineNumber(lineNum);
831 std::vector<std::unique_ptr<ASTNode>> arguments;
837 auto funcCallNode = std::make_unique<FuncCallNode>(name, std::move(arguments));
838 funcCallNode->setLineNumber(lineNum);
844 int lineNum =
token->getLine();
849 std::vector<std::unique_ptr<CaseStmtNode::CaseBranch>> branches;
851 std::vector<std::unique_ptr<ASTNode>> values;
860 branches.push_back(std::make_unique<CaseStmtNode::CaseBranch>(std::move(values), std::move(statement)));
864 std::unique_ptr<ASTNode> elseStatement =
nullptr;
873 auto caseStmtNode = std::make_unique<CaseStmtNode>(std::move(expression), std::move(branches), std::move(elseStatement));
874 caseStmtNode->setLineNumber(lineNum);
880 int lineNum =
token->getLine();
882 std::vector<std::unique_ptr<ConstDeclNode::ConstAssignment>> assignments;
885 std::string identifier =
token->getTokenValue();
890 assignments.push_back(std::make_unique<ConstDeclNode::ConstAssignment>(identifier, std::move(value)));
894 auto constDeclNode = std::make_unique<ConstDeclNode>(std::move(assignments));
895 constDeclNode->setLineNumber(lineNum);
896 return constDeclNode;
900 std::vector<std::unique_ptr<ASTNode>> declarations;
904 }
else if (
peekIs(
"type")) {
906 }
else if (
peekIs(
"const")) {
908 }
else if (
peekIs(
"var")) {
912 declarations.push_back(std::move(decl));
915 }
else if (
peekIs(
"procedure")) {
917 }
else if (
peekIs(
"function")) {
925 std::vector<std::unique_ptr<ASTNode>> statements;
940 std::vector<std::unique_ptr<ASTNode>> arguments;
980 error(
"Invalid relational operator");
986 int lineNum =
token->getLine();
989 std::vector<std::unique_ptr<ASTNode>> typeDeclarations;
993 std::string typeName =
token->getTokenValue();
998 std::unique_ptr<ASTNode> typeDefinition;
1006 typeDefinition = std::make_unique<RecordDeclarationNode>(
1008 std::unique_ptr<RecordTypeNode>(
static_cast<RecordTypeNode *
>(recordType.release())));
1009 }
else if (
peekIs(
"(")) {
1012 std::vector<std::string> enumValues;
1014 enumValues.push_back(
token->getTokenValue());
1019 enumValues.push_back(
token->getTokenValue());
1024 typeDefinition = std::make_unique<EnumTypeDeclNode>(typeName, std::move(enumValues));
1025 }
else if (
peekIs(
"array")) {
1027 typeDefinition = std::make_unique<ArrayTypeDeclarationNode>(
1029 std::unique_ptr<ArrayTypeNode>(
static_cast<ArrayTypeNode *
>(arrayType.release())));
1030 }
else if (
peekIs(
"set")) {
1035 std::string baseType =
token->getTokenValue();
1037 typeDefinition = std::make_unique<TypeAliasNode>(typeName,
"set of " + baseType);
1038 }
else if (
peekIs(
"file")) {
1045 typeDefinition = std::make_unique<TypeAliasNode>(typeName,
"file");
1046 }
else if (
peekIs(
"^")) {
1049 std::string baseType =
token->getTokenValue();
1051 typeDefinition = std::make_unique<TypeAliasNode>(typeName,
"^" + baseType);
1054 std::string baseType =
token->getTokenValue();
1056 typeDefinition = std::make_unique<TypeAliasNode>(typeName, baseType);
1062 typeDeclarations.push_back(std::move(typeDefinition));
1065 auto typeDeclNode = std::make_unique<TypeDeclNode>(std::move(typeDeclarations));
1066 typeDeclNode->setLineNumber(lineNum);
1067 return typeDeclNode;
1073 std::vector<std::unique_ptr<ASTNode>> fields;
1075 std::vector<std::string> ids;
1077 ids.push_back(
token->getTokenValue());
1082 ids.push_back(
token->getTokenValue());
1088 fields.push_back(std::make_unique<VarDeclNode>(
1090 std::move(fieldType),
1091 std::vector<std::unique_ptr<ASTNode>>{}));
1096 auto recordNode = std::make_unique<RecordTypeNode>(std::move(fields));
1102 recordNode->variantTagName =
token->getTokenValue();
1107 recordNode->variantTagType =
token->getTokenValue();
1126 std::vector<std::string> ids;
1128 ids.push_back(
token->getTokenValue());
1133 ids.push_back(
token->getTokenValue());
1139 arm.
fields.push_back(std::make_unique<VarDeclNode>(
1141 std::move(fieldType),
1142 std::vector<std::unique_ptr<ASTNode>>{}));
1150 recordNode->variantArms.push_back(std::move(arm));
1160 std::vector<std::string> identifiers;
1161 std::vector<std::unique_ptr<ASTNode>> initializers;
1165 identifiers.push_back(
token->getTokenValue());
1186 return std::make_unique<VarDeclNode>(
1187 std::move(identifiers),
1189 std::move(initializers));
1200 std::string baseType =
token->getTokenValue();
1202 return std::make_unique<SetTypeNode>(baseType);
1211 return std::make_unique<SimpleTypeNode>(
"file");
1220 std::string baseType =
token->getTokenValue();
1222 return std::make_unique<PointerTypeNode>(baseType);
1225 auto t = std::make_unique<SimpleTypeNode>(
token->getTokenValue());
1237 return std::make_unique<ArrayTypeNode>(
1238 std::move(elementType),
1254 return std::make_unique<ArrayTypeNode>(
1255 std::move(elementType),
1256 std::move(lowerBound),
1257 std::move(upperBound));
1263 return "identifier";
1271 return "unknown token";
1278 std::string name =
token->getTokenValue();
1281 std::unique_ptr<ASTNode> left = std::make_unique<VariableNode>(name);
1282 left->setLineNumber(lineNum);
1290 left = std::make_unique<ArrayAccessNode>(std::move(left), std::move(
index));
1291 left->setLineNumber(lineNum);
1292 }
else if (
peekIs(
".")) {
1295 std::string fieldName =
token->getTokenValue();
1297 left = std::make_unique<FieldAccessNode>(std::move(left), fieldName);
1298 left->setLineNumber(lineNum);
1299 }
else if (
peekIs(
"^")) {
1301 left = std::make_unique<PointerDerefNode>(std::move(left));
1302 left->setLineNumber(lineNum);
1312 int lineNum =
token->getLine();
1315 std::string recordVar =
token->getTokenValue();
1320 auto withNode = std::make_unique<WithStmtNode>(recordVar, std::move(stmt));
1321 withNode->setLineNumber(lineNum);
1327 int lineNum =
token->getLine();
1330 std::string label =
token->getTokenValue();
1332 auto gotoNode = std::make_unique<GotoStmtNode>(label);
1333 gotoNode->setLineNumber(lineNum);
scan::TToken * token
current token pointer
scan::Scanner scanner
underlying scanner
bool peekIs(const std::string &s)
Check if the current token's value matches a string (case-insensitive).
size_t index
current token index
bool next()
Advance to the next token; returns false at end of stream.
AST node for an array type (array[lower..upper] of elementType).
OpType
Binary operator kinds.
AST node for accessing a record field (record.field).
Exception thrown on parse errors.
std::unique_ptr< ASTNode > parseWithStatement()
Parse a with statement.
bool match(const std::string &s)
Try to match and consume a token by value.
std::unique_ptr< ASTNode > parseTypeDeclaration()
Parse a type declaration section.
std::vector< std::unique_ptr< ASTNode > > parseStatementList()
Parse a list of statements (separated by semicolons).
void error(const std::string &message)
Report a parse error with the given message.
std::unique_ptr< ASTNode > parseVarDeclaration()
Parse a var declaration section.
std::unique_ptr< ASTNode > parseExpression()
Parse a full expression (simple expression with optional relational op).
std::unique_ptr< ASTNode > parseGotoStatement()
Parse a goto statement.
std::unique_ptr< ASTNode > parseProcedureDeclaration()
Parse a procedure declaration.
std::unique_ptr< ASTNode > parseParameter()
Parse a single formal parameter.
std::unique_ptr< ASTNode > parseTypeSpec()
Parse a type specifier.
void expectToken(const std::string &expected)
Consume a token matching the expected string, or throw.
void parseLabelDeclaration()
Parse a label declaration section (label 100, 200;).
std::unique_ptr< ProgramNode > parseProgram()
Parse a complete Pascal program and return the root AST node.
bool isKeyword(const std::string &s)
Check if a string is a reserved keyword.
std::unique_ptr< ASTNode > parseRecordType()
Parse a record type definition.
std::unique_ptr< ASTNode > parseForStatement()
Parse a for-to/downto-do statement.
std::unique_ptr< ASTNode > parseIfStatement()
Parse an if-then-else statement.
std::unique_ptr< ASTNode > parseSimpleExpression()
Parse a simple expression (terms combined by +, -, or).
std::unique_ptr< ASTNode > parseConstDeclaration()
Parse a const declaration section.
std::vector< std::unique_ptr< ASTNode > > parseParameterList()
Parse a formal parameter list.
std::unique_ptr< ASTNode > parseAssignmentOrProcCall()
Parse an assignment or procedure call starting with an identifier.
std::unique_ptr< BlockNode > parseBlock()
Parse a block (declarations + compound statement).
std::unique_ptr< UnitNode > parseUnit()
Parse a Pascal unit and return the root AST node.
std::unique_ptr< ASTNode > parseProcedureForwardDecl()
Parse a procedure forward declaration (signature only, no body).
std::unordered_set< std::string > declaredLabels
Set of user-declared goto labels.
std::vector< std::unique_ptr< ASTNode > > parseArgumentList()
Parse a comma-separated argument list.
bool isUnitSource() const
Check if the source starts with a 'unit' keyword.
bool isMulOperator()
Check if current token is a multiplicative operator.
std::vector< std::unique_ptr< ASTNode > > parseInterfaceDeclarations()
Parse interface forward declarations (procedure/function signatures only).
std::string tokenTypeToString(types::TokenType type)
Convert a TokenType to its display string.
std::unique_ptr< ASTNode > parseFunctionDeclaration()
Parse a function declaration.
std::vector< std::unique_ptr< ASTNode > > parseDeclarations()
Parse the declarations section.
std::unique_ptr< ASTNode > parseFunctionForwardDecl()
Parse a function forward declaration (signature only, no body).
std::unique_ptr< ASTNode > parseFunctionCall(const std::string &name)
Parse a function call given its already-parsed name.
void removeBraceComments()
Remove {brace} comments from the token stream.
std::unique_ptr< ASTNode > parseArrayType()
Parse an array type specification.
std::unique_ptr< ASTNode > parseCaseStatement()
Parse a case statement.
std::unique_ptr< ASTNode > parseLValue()
Parse an lvalue (variable, array access, pointer deref, field access).
std::unique_ptr< ASTNode > parseProcedureCall(const std::string &name)
Parse a procedure call given its already-parsed name.
std::unique_ptr< ASTNode > parseFactor()
Parse a factor (literal, variable, function call, sub-expression).
std::unique_ptr< ASTNode > parseWhileStatement()
Parse a while-do statement.
std::unique_ptr< ASTNode > parseTerm()
Parse a term (factors combined by *, /, div, mod, and).
std::unique_ptr< ASTNode > parseRepeatStatement()
Parse a repeat-until statement.
std::string getRelationalOp()
Consume and return a relational operator string.
std::unique_ptr< CompoundStmtNode > parseCompoundStatement()
Parse a compound statement (begin..end).
std::unique_ptr< ASTNode > parseStatement()
Parse a single statement.
bool isRelationalOperator()
Check if current token is a relational operator.
AST node for a record type (record ... end).
Operator
Unary operator kinds.
AST node for a variable reference.
TokenType
Classification of scanned tokens.
@ TT_SYM
symbol / operator token
@ TT_ID
identifier or keyword
@ TT_NUM
decimal numeric literal
Pascal recursive-descent parser producing a Pascal AST.
A single variant arm inside a variant record.
std::vector< std::unique_ptr< ASTNode > > fields
field declarations in this arm
std::vector< std::unique_ptr< ASTNode > > caseLabels
case constant(s) for this arm