MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
validator.hpp
Go to the documentation of this file.
1
6#ifndef __VALIDATOR_H_
7#define __VALIDATOR_H_
8
9#include "scanner/scanner.hpp"
10#include "scanner/types.hpp"
11#include <string>
12#include <unordered_map>
13#include <unordered_set>
14
15namespace mxx {
16
18 struct Scope {
19 std::unordered_set<std::string> vars;
20 std::unordered_set<std::string> consts;
21 std::unordered_set<std::string> types;
22 std::unordered_set<std::string> funcs;
23 std::unordered_set<std::string> procs;
24 std::unordered_set<std::string> params;
25 };
26
35 public:
40 explicit TPValidator(const std::string &source_);
41
47 bool validate(const std::string &name);
48
49 private:
50 std::unordered_map<std::string, std::unordered_set<std::string>> recordFieldScopesByType;
52 std::vector<Scope> scopeStack;
54 const scan::TToken *token = nullptr;
55 std::string source;
56 std::string filename;
57 size_t index = 0;
59
61 bool isPascalKeyword(const std::string &s) const;
62
63 std::unordered_set<std::string> declaredVars;
64 std::unordered_set<std::string> declaredConsts;
65 std::unordered_set<std::string> declaredFuncs;
66 std::unordered_set<std::string> declaredProcs;
67 std::unordered_set<std::string> importedUnits;
69 void pushScope();
71 void popScope();
75 const Scope *currentScope() const;
77 bool isVariableInCurrentScope(const std::string &name) const;
79 std::string currentScopeName() const;
80
82 bool isVarDeclaredHere(const std::string &name) const;
84 bool isTypeDeclaredHere(const std::string &name) const;
86 bool isFuncDeclaredHere(const std::string &name) const;
88 bool isProcDeclaredHere(const std::string &name) const;
90 bool isParamDeclaredHere(const std::string &name) const;
92 void declareVar(const std::string &name, const scan::TToken *at);
94 void declareConst(const std::string &name, const scan::TToken *at);
96 void declareFunc(const std::string &name, const scan::TToken *at);
98 void declareProc(const std::string &name, const scan::TToken *at);
100 void declareParam(const std::string &name, const scan::TToken *at);
101
103 void checkVar(const std::string &name, const scan::TToken *at);
105 void checkVarOrConst(const std::string &name, const scan::TToken *at);
107 void checkConstOnly(const std::string &name, const scan::TToken *at);
108
114 void parseConstExpr(const std::unordered_set<std::string> &stops,
115 bool constOnly);
116
117 std::unordered_set<std::string> declaredTypes;
118
120 bool isBuiltinType() const;
122 void declareType(const std::string &name, const scan::TToken *at);
124 void checkType(const std::string &name, const scan::TToken *at);
126 bool isBuiltinConst(const std::string &name) const;
128 bool next();
130 bool match(const std::string &s) const;
132 bool match(types::TokenType t) const;
134 bool peekIs(const std::string &s);
135
137 void require(const std::string &s);
141 void requireKW(const std::string &k);
142
144 void fail(const std::string &msg);
146 void failHere(const std::string &msg);
148 void failAt(const scan::TToken *at, const std::string &msg);
149
151 static std::string tokenTypeToString(types::TokenType t);
153 static std::string lower(std::string s);
155 std::string found() const;
157 bool isKW(const std::string &k) const;
158
160 void parseProgram();
162 void parseUnit();
166 void parseUses();
168 void parseBlock();
170 void parseLabelSection();
172 void parseConstSection();
174 void parseTypeSection();
176 void parseVarSection();
178 void parseSubprogram();
180 void parseFormalParams();
182 void parseIdentList();
184 void parseType(const std::string &);
186 void parseTypeName();
188 void parseSubrange();
190 void parseConstant();
192 void parseConstSimple();
196 void parseStatement();
198 void parseIf();
200 void parseWhile();
202 void parseRepeat();
204 void parseFor();
206 void parseCase();
208 void parseCaseLabelList();
210 void parseCaseLabel();
212 void parseWith();
214 void parseGoto();
218 void parseDesignator();
220 void parseActualParams();
222 void parseExprStop(const std::unordered_set<std::string> &stops);
223
225 bool isRelOp() const;
227 bool isAddOp() const;
229 bool isMulOp() const;
231 bool isSetOp() const;
232
233 private:
235 static std::string toLower(const std::string &s);
237 void predeclareType(const std::string &name);
239 bool isBuiltinTypeName(const std::string &key) const;
241 void pushRecordFieldScope(const std::string &recordTypeName);
243 void popRecordFieldScope();
245 bool inRecordFieldScope() const;
246
248 void declareRecordField(const std::string &name, const scan::TToken *at);
250 void parseFieldIdentList();
251
252 int withDepth = 0;
253 };
254
255} // namespace mxx
256#endif
void declareProc(const std::string &name, const scan::TToken *at)
Declare a procedure in the current scope.
void pushRecordFieldScope(const std::string &recordTypeName)
Push a record field scope for the given type.
bool isVariableInCurrentScope(const std::string &name) const
Check if a variable is declared in the current scope.
void parseUnit()
Validate a Pascal unit.
void parseWith()
Validate a with statement.
bool isBuiltinConst(const std::string &name) const
Check if a name is a built-in constant (true, false, maxint).
void parseVarSection()
Validate a var section.
void pushScope()
Push a new scope onto the scope stack.
int withDepth
nesting depth of with statements (suppress undeclared-id errors)
std::string currentRecordTypeName
name of record type currently being parsed
Definition validator.hpp:51
void require(const std::string &s)
Require the current token to match a string, or fail.
bool inRecordFieldScope() const
Check if currently inside a record field scope.
void declareType(const std::string &name, const scan::TToken *at)
Declare a user-defined type in the current scope.
bool isAddOp() const
Check if current token is an additive operator.
void parseExprStop(const std::unordered_set< std::string > &stops)
Validate an expression up to a set of stop tokens.
std::vector< Scope > scopeStack
stack of lexical scopes
Definition validator.hpp:52
bool isVarDeclaredHere(const std::string &name) const
Check if a variable is declared in the innermost scope.
void parseIf()
Validate an if statement.
void failHere(const std::string &msg)
Report a validation error at the current token.
void parseActualParams()
Validate actual parameter list.
bool isParamDeclaredHere(const std::string &name) const
Check if a parameter is declared in the innermost scope.
void parseDesignator()
Validate a designator (variable with selectors).
scan::Scanner scanner
underlying scanner
Definition validator.hpp:53
void parseType(const std::string &)
Validate a type specification.
void requireKW(const std::string &k)
Require the current token to be a keyword, or fail.
std::unordered_set< std::string > declaredVars
globally declared variables
Definition validator.hpp:63
bool isBuiltinTypeName(const std::string &key) const
Check if a lowercase key is a built-in type name.
void parseTypeName()
Validate a type name reference.
static std::string toLower(const std::string &s)
Convert a string to lowercase (static helper).
void parseConstSection()
Validate a const section.
void parseLabelSection()
Validate a label section.
const scan::TToken * token
current token pointer
Definition validator.hpp:54
void declareRecordField(const std::string &name, const scan::TToken *at)
Declare a record field in the current record scope.
void declareFunc(const std::string &name, const scan::TToken *at)
Declare a function in the current scope.
std::unordered_set< std::string > declaredProcs
globally declared procedures
Definition validator.hpp:66
void declareParam(const std::string &name, const scan::TToken *at)
Declare a parameter in the current scope.
static std::string lower(std::string s)
Convert a string to lowercase.
bool isProcDeclaredHere(const std::string &name) const
Check if a procedure is declared in the innermost scope.
std::unordered_set< std::string > declaredFuncs
globally declared functions
Definition validator.hpp:65
void parseCaseLabel()
Validate a single case label.
void checkConstOnly(const std::string &name, const scan::TToken *at)
Assert a name is a constant (used in const expressions).
void parseCase()
Validate a case statement.
std::unordered_set< std::string > declaredConsts
globally declared constants
Definition validator.hpp:64
std::unordered_map< std::string, std::unordered_set< std::string > > recordFieldScopesByType
field names per record type
Definition validator.hpp:50
void parseInterfaceSection()
Validate interface section declarations.
void declareConst(const std::string &name, const scan::TToken *at)
Declare a constant in the current scope.
bool match(const std::string &s) const
Check if the current token value matches a string.
Definition validator.cpp:76
void parseTypeSection()
Validate a type section.
void declareVar(const std::string &name, const scan::TToken *at)
Declare a variable in the current scope.
std::string filename
source filename for error messages
Definition validator.hpp:56
void parseSubprogram()
Validate a procedure or function declaration.
bool isSetOp() const
Check if current token is a set operator.
void parseGoto()
Validate a goto statement.
void parseUses()
Validate a uses clause.
void parseConstExpr(const std::unordered_set< std::string > &stops, bool constOnly)
Parse and validate a constant expression.
void parseConstSimple()
Validate a simple constant (number, string, or name).
void checkVarOrConst(const std::string &name, const scan::TToken *at)
Assert a name is a variable or constant in scope.
void parseRepeat()
Validate a repeat..until statement.
void parseCaseLabelList()
Validate a case label list.
void parseFor()
Validate a for statement.
std::unordered_set< std::string > importedUnits
unit names from uses clause
Definition validator.hpp:67
void popRecordFieldScope()
Pop the current record field scope.
static std::string tokenTypeToString(types::TokenType t)
Convert a TokenType to a display string.
void parseCompoundStatement()
Validate a compound statement (begin..end).
std::unordered_set< std::string > declaredTypes
globally declared type names
void parseIdentList()
Validate a comma-separated identifier list.
void popScope()
Pop the current scope from the stack.
bool peekIs(const std::string &s)
Check if the current token value matches (and optionally advance).
Definition validator.cpp:98
bool isRelOp() const
Check if current token is a relational operator.
void parseWhile()
Validate a while statement.
void checkType(const std::string &name, const scan::TToken *at)
Assert a type name is declared and accessible.
size_t index
current token index
Definition validator.hpp:57
bool isPascalKeyword(const std::string &s) const
Check if a string is a Pascal reserved keyword.
Scope * currentScope()
Get the current (top) scope.
void checkVar(const std::string &name, const scan::TToken *at)
Assert a variable is declared and accessible in scope.
std::string source
original source text
Definition validator.hpp:55
bool next()
Advance to the next token.
Definition validator.cpp:84
void parseFieldIdentList()
Parse a field identifier list within a record definition.
bool isMulOp() const
Check if current token is a multiplicative operator.
std::string currentScopeName() const
Return a display name for the current scope.
void parseFormalParams()
Validate formal parameter declarations.
void fail(const std::string &msg)
Report a validation error with a generic message.
TPValidator(const std::string &source_)
Construct a validator for the given source.
Definition validator.cpp:16
std::string found() const
Return a display string for the current token value.
bool isBuiltinType() const
Check if the current token is a built-in type name.
void parseSimpleOrCallOrAssign()
Validate a simple statement, procedure call, or assignment.
bool validate(const std::string &name)
Run semantic validation.
Definition validator.cpp:18
void parseStatement()
Validate a single statement.
void parseBlock()
Validate a block (declarations + compound statement).
void parseSubrange()
Validate a subrange type.
bool isTypeDeclaredHere(const std::string &name) const
Check if a type is declared in the innermost scope.
void predeclareType(const std::string &name)
Pre-declare a built-in or forward-declared type.
bool isKW(const std::string &k) const
Check if current token value (lowercased) matches a keyword.
void failAt(const scan::TToken *at, const std::string &msg)
Report a validation error at a specific token.
bool isFuncDeclaredHere(const std::string &name) const
Check if a function is declared in the innermost scope.
void parseConstant()
Validate a constant value.
void parseProgram()
Validate a complete Pascal program.
Lexical scanner that tokenizes source text.
Definition scanner.hpp:28
Definition expr.cpp:8
token::Token< char > TToken
Default token type.
Definition scanner.hpp:19
TokenType
Classification of scanned tokens.
Definition types.hpp:16
Token, character, and operator type enumerations for the scanner.
Lexical scanner that tokenizes source text into typed tokens.
A single scope level, tracking declared identifiers by category.
Definition validator.hpp:18
std::unordered_set< std::string > consts
constant names
Definition validator.hpp:20
std::unordered_set< std::string > procs
procedure names
Definition validator.hpp:23
std::unordered_set< std::string > funcs
function names
Definition validator.hpp:22
std::unordered_set< std::string > params
parameter names
Definition validator.hpp:24
std::unordered_set< std::string > vars
variable names
Definition validator.hpp:19