New error system

This commit is contained in:
ala89 2023-12-15 14:11:44 +01:00
parent 8e853aaaf2
commit eb29c03359
7 changed files with 89 additions and 69 deletions

View File

@ -9,7 +9,7 @@ bool bool_castable(AnalysisResult type) {
void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos) { void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos) {
if (holds_alternative<monostate>(res1) || holds_alternative<monostate>(res2)) { if (holds_alternative<monostate>(res1) || holds_alternative<monostate>(res2)) {
throw TypeError("Incomparable values", pos); throw TypeError(ErrorType::TypesNotComparable, pos);
} }
Type type1 = get<Type>(res1); Type type1 = get<Type>(res1);
@ -25,11 +25,11 @@ void check_comparable(AnalysisResult res1, AnalysisResult res2, CodePosition pos
return; return;
} }
default: default:
throw TypeError("Incomparable values", pos); throw TypeError(ErrorType::TypesNotComparable, pos);
} }
} }
default: default:
throw TypeError("Incomparable values", pos); throw TypeError(ErrorType::TypesNotComparable, pos);
} }
} }
@ -53,7 +53,7 @@ Type try_string_to_type(string type_name, CodePosition pos) {
Type type = string_to_type(type_name); Type type = string_to_type(type_name);
return type; return type;
} catch (...) { } catch (...) {
throw TypeError("Unknown type '"+type_name+"'", pos); throw TypeError(ErrorType::UnknownType, pos, type_name);
} }
} }
@ -74,7 +74,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data); string identifier = get<string>(token.data);
if (!memory.contains(identifier)) if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", token.pos); throw RuntimeError(ErrorType::UnknownIdentifier, token.pos, identifier);
return memory.get(identifier).type; return memory.get(identifier).type;
throw exception(); throw exception();
@ -100,7 +100,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
case NodeType::If: case NodeType::If:
case NodeType::IfElse: { case NodeType::IfElse: {
if (!bool_castable(analyze(node.children[0], memory))) { if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
} }
analyze(node.children[1], memory); analyze(node.children[1], memory);
@ -111,7 +111,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
} break; } break;
case NodeType::While: { case NodeType::While: {
if (!bool_castable(analyze(node.children[0], memory))) { if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find a cast to bool", get_node_pos(node.children[0])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
} }
analyze(node.children[1], memory); analyze(node.children[1], memory);
@ -123,7 +123,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
analyze(node.children[0], memory); analyze(node.children[0], memory);
if (!bool_castable(analyze(node.children[1], memory))) { if (!bool_castable(analyze(node.children[1], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[1])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
} }
analyze(node.children[2], memory); analyze(node.children[2], memory);
@ -142,17 +142,17 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
case NodeType::Lor: case NodeType::Lor:
case NodeType::Land: { case NodeType::Land: {
if (!bool_castable(analyze(node.children[0], memory))) { if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
} }
if (!bool_castable(analyze(node.children[1], memory))) { if (!bool_castable(analyze(node.children[1], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[1])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[1]), "bool");
} }
return Type::Int; return Type::Int;
} break; } break;
case NodeType::Neg: { case NodeType::Neg: {
if (!bool_castable(analyze(node.children[0], memory))) { if (!bool_castable(analyze(node.children[0], memory))) {
throw TypeError("Can't find an explicit cast to bool", get_node_pos(node.children[0])); throw TypeError(ErrorType::TypeNotCastable, get_node_pos(node.children[0]), "bool");
} }
return Type::Int; return Type::Int;
@ -184,10 +184,10 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
AnalysisResult e2 = analyze(node.children[1], memory); AnalysisResult e2 = analyze(node.children[1], memory);
if (holds_alternative<monostate>(e1) || get<Type>(e1) != Type::Int) { if (holds_alternative<monostate>(e1) || get<Type>(e1) != Type::Int) {
throw TypeError("Expression must have integral type", get_node_pos(node.children[0])); throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[0]));
} }
if (holds_alternative<monostate>(e2) || get<Type>(e2) != Type::Int) { if (holds_alternative<monostate>(e2) || get<Type>(e2) != Type::Int) {
throw TypeError("Expression must have integral type", get_node_pos(node.children[1])); throw TypeError(ErrorType::ExpectedIntegralType, get_node_pos(node.children[1]));
} }
return Type::Int; return Type::Int;
@ -197,7 +197,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
AnalysisResult res = analyze(node.children[0], memory); AnalysisResult res = analyze(node.children[0], memory);
if (holds_alternative<monostate>(res) || !is_arithmetic_type(get<Type>(res))) { if (holds_alternative<monostate>(res) || !is_arithmetic_type(get<Type>(res))) {
throw TypeError("Expressions must have arithmetic type", get_node_pos(node.children[1])); throw TypeError(ErrorType::ExpectedArithmeticType, get_node_pos(node.children[0]));
} }
return get<Type>(res); return get<Type>(res);
@ -210,7 +210,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data); string identifier = get<string>(token.data);
if (memory.contains_top(identifier)) if (memory.contains_top(identifier))
throw RuntimeError("Already defined identifier \""+identifier+"\"", token.pos); throw RuntimeError(ErrorType::AlreadyDefinedIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos); Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type); memory.declare(identifier, type);
@ -225,7 +225,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data); string identifier = get<string>(token.data);
if (memory.contains_top(identifier)) if (memory.contains_top(identifier))
throw TypeError("Already defined identifier \""+identifier+"\"", token.pos); throw RuntimeError(ErrorType::AlreadyDefinedIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos); Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type); memory.declare(identifier, type);
@ -238,7 +238,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]); Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
Type type = memory.get(identifier).type; Type type = memory.get(identifier).type;
AnalysisResult res = analyze(node.children[1], memory); AnalysisResult res = analyze(node.children[1], memory);
@ -255,7 +255,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(identifierTok.data); string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier)) if (!memory.contains(identifier))
throw RuntimeError("Unknown identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
return memory.get(identifier).type; return memory.get(identifier).type;
} }

View File

@ -12,20 +12,16 @@ using namespace std;
*/ */
EvalResult eval(Node &ast, Memory& memory); EvalResult eval(Node &ast, Memory& memory);
class BreakException : public runtime_error { class BreakException : public InternalError {
public: public:
explicit BreakException(const string& message, CodePosition pos) explicit BreakException(CodePosition pos)
: runtime_error(message), pos(pos) {} : InternalError(pos) {}
const CodePosition pos;
}; };
class ContinueException : public runtime_error { class ContinueException : public InternalError {
public: public:
explicit ContinueException(const string& message, CodePosition pos) explicit ContinueException(CodePosition pos)
: runtime_error(message), pos(pos) {} : InternalError(pos) {}
const CodePosition pos;
}; };
#endif #endif

View File

@ -10,10 +10,10 @@ using namespace std;
/** /**
* Utilisé pour revenir en arrière quand quelque chose n'est pas reconnu * Utilisé pour revenir en arrière quand quelque chose n'est pas reconnu
*/ */
class ParseException : public std::exception { class ParseException : public InternalError {
const char* what() const noexcept override { public:
return "Parse Exception"; explicit ParseException(CodePosition pos = {})
} : InternalError(pos) {}
}; };
/** /**

View File

@ -183,26 +183,50 @@ struct Scope {
/** /**
* Errors * Errors
*/ */
class SyntaxError : public runtime_error { enum class ErrorType { DivisionByZero, ModuloByZero, ExpectedIntegralType, ExpectedArithmeticType, UninitializedIdentifier, UnknownIdentifier, AlreadyDefinedIdentifier, EmptyInput, UnknownToken, InvalidSyntax, ExceptedLParen, ExpectedRParen, ExpectedRCurlyBracket, ExpectedSemicolon, DependentDeclaration, TypesNotComparable, TypeNotCastable, UnknownType };
using ErrorData = variant<monostate, string>;
class UserError : public exception {
public: public:
explicit SyntaxError(const string& message, CodePosition pos) explicit UserError(ErrorType type, CodePosition pos, ErrorData data = {})
: runtime_error(message), pos(pos) {} : pos(pos), type(type), data(data) {}
const char* what() const noexcept override {
return "User error occurred.";
}
const CodePosition pos; const CodePosition pos;
const ErrorType type;
const ErrorData data;
}; };
class TypeError : public runtime_error { class SyntaxError : public UserError {
public: public:
explicit TypeError(const string& message, CodePosition pos) explicit SyntaxError(ErrorType type, CodePosition pos, ErrorData data = {})
: runtime_error(message), pos(pos) {} : UserError(type, pos, data) {}
const CodePosition pos;
}; };
class RuntimeError : public runtime_error { class TypeError : public UserError {
public: public:
explicit RuntimeError(const string& message, CodePosition pos) explicit TypeError(ErrorType type, CodePosition pos, ErrorData data = {})
: runtime_error(message), pos(pos) {} : UserError(type, pos, data) {}
};
class RuntimeError : public UserError {
public:
explicit RuntimeError(ErrorType type, CodePosition pos, ErrorData data = {})
: UserError(type, pos, data) {}
};
class InternalError : public exception {
public:
explicit InternalError(CodePosition pos = {})
: pos(pos) {}
const char* what() const noexcept override {
return "Internal error occurred.";
}
const CodePosition pos; const CodePosition pos;
}; };

View File

@ -241,13 +241,13 @@ EvalResult eval(Node &ast, Memory &memory) {
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) { if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
double d1 = double_cast(e1); double d1 = double_cast(e1);
double d2 = double_cast(e2); double d2 = double_cast(e2);
if (d2 == 0) throw RuntimeError("Division by 0", node.pos); if (d2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
return d1 / d2; return d1 / d2;
} }
else { else {
int i1 = get<int>(e1); int i1 = get<int>(e1);
int i2 = get<int>(e2); int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError("Division by 0", node.pos); if (i2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
return i1 / i2; return i1 / i2;
} }
} break; } break;
@ -257,7 +257,7 @@ EvalResult eval(Node &ast, Memory &memory) {
int i1 = get<int>(e1); int i1 = get<int>(e1);
int i2 = get<int>(e2); int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError("Modulo by 0", node.pos); if (i2 == 0) throw RuntimeError(ErrorType::ModuloByZero, node.pos);
return i1 % i2; return i1 % i2;
} break; } break;
case NodeType::UnaryPlus: { case NodeType::UnaryPlus: {
@ -332,7 +332,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier); MemoryVar& var = memory.get(identifier);
if (!var.initialized) { if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
} }
else if (var.type == Type::Int) { else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) + 1); memory.update(identifier, get<int>(var.value) + 1);
@ -349,7 +349,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier); MemoryVar& var = memory.get(identifier);
if (!var.initialized) { if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
} }
else if (var.type == Type::Int) { else if (var.type == Type::Int) {
int oldVal = get<int>(var.value); int oldVal = get<int>(var.value);
@ -367,7 +367,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier); MemoryVar& var = memory.get(identifier);
if (!var.initialized) { if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
} }
else if (var.type == Type::Int) { else if (var.type == Type::Int) {
memory.update(identifier, get<int>(var.value) - 1); memory.update(identifier, get<int>(var.value) - 1);
@ -384,7 +384,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier); MemoryVar& var = memory.get(identifier);
if (!var.initialized) { if (!var.initialized) {
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", identifierTok.pos); throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
} }
else if (var.type == Type::Int) { else if (var.type == Type::Int) {
int oldVal = get<int>(var.value); int oldVal = get<int>(var.value);
@ -396,7 +396,7 @@ EvalResult eval(Node &ast, Memory &memory) {
} }
} }
default: { default: {
throw RuntimeError("Not Implemented", node.pos); throw exception();
} }
} }
} }
@ -419,15 +419,15 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier); MemoryVar& var = memory.get(identifier);
if (!var.initialized) if (!var.initialized)
throw RuntimeError("Accessing uninitialized identifier \""+identifier+"\"", token.pos); throw RuntimeError(ErrorType::UninitializedIdentifier, token.pos, identifier);
return var.value; return var.value;
} break; } break;
case TokenType::Break: { case TokenType::Break: {
throw BreakException("", token.pos); throw BreakException(token.pos);
} break; } break;
case TokenType::Continue: { case TokenType::Continue: {
throw ContinueException("", token.pos); throw ContinueException(token.pos);
} break; } break;
default: default:
throw exception(); throw exception();

View File

@ -55,14 +55,14 @@ Node parse(vector<Token> tokens) {
reverse(tokens.begin(), tokens.end()); reverse(tokens.begin(), tokens.end());
if (tokens.size() == 0) { if (tokens.size() == 0) {
throw SyntaxError("Input must not be empty", null_pos); throw SyntaxError(ErrorType::EmptyInput, null_pos);
} }
ParseReturn ret = parse_prog(tokens); ParseReturn ret = parse_prog(tokens);
if (ret.tokens.size() != 0) { if (ret.tokens.size() != 0) {
CodePosition pos = ret.tokens.back().pos; CodePosition pos = ret.tokens.back().pos;
throw SyntaxError("Unable to parse", pos); throw SyntaxError(ErrorType::InvalidSyntax, pos);
} }
return ret.node; return ret.node;
@ -169,7 +169,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back(); tokens.pop_back();
if (tokens.back().type != TokenType::Semicolon) if (tokens.back().type != TokenType::Semicolon)
throw SyntaxError("Expected ';'", tokens.back().pos); throw SyntaxError(ErrorType::ExpectedSemicolon, tokens.back().pos);
tokens.pop_back(); tokens.pop_back();
return { return {
@ -195,7 +195,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back(); tokens.pop_back();
if (tokens.back().type != TokenType::LParenthese) // Opening ( if (tokens.back().type != TokenType::LParenthese) // Opening (
throw SyntaxError("Missing '('", tokens.back().pos); throw SyntaxError(ErrorType::ExceptedLParen, tokens.back().pos);
tokens.pop_back(); tokens.pop_back();
ParseReturn ret = parse_expr(tokens); // Expr ParseReturn ret = parse_expr(tokens); // Expr
@ -203,7 +203,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
int nb_tok = ret.tokens.size(); // Closing ) int nb_tok = ret.tokens.size(); // Closing )
if (nb_tok == 0 || ret.tokens.back().type != TokenType::RParenthese) if (nb_tok == 0 || ret.tokens.back().type != TokenType::RParenthese)
throw SyntaxError( throw SyntaxError(
"Missing ')'", ErrorType::ExpectedRParen,
nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos
); );
@ -215,7 +215,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
ret = parse_instruction(tokens); // Instruction1 ret = parse_instruction(tokens); // Instruction1
} catch (const ParseException& pex) { } catch (const ParseException& pex) {
throw SyntaxError( throw SyntaxError(
"Invalid Syntax", ErrorType::InvalidSyntax,
pos=tokens.back().pos pos=tokens.back().pos
); );
} }
@ -224,7 +224,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
( get<InnerNode>(ret.node).type == NodeType::AssignedDeclaration || ( get<InnerNode>(ret.node).type == NodeType::AssignedDeclaration ||
get<InnerNode>(ret.node).type == NodeType::Declaration ) ) get<InnerNode>(ret.node).type == NodeType::Declaration ) )
throw SyntaxError( throw SyntaxError(
"a dependent statement may not be a declaration", ErrorType::DependentDeclaration,
pos=tokens.back().pos pos=tokens.back().pos
); );
@ -263,7 +263,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back(); tokens.pop_back();
if (tokens.back().type != TokenType::LParenthese) // Opening ( if (tokens.back().type != TokenType::LParenthese) // Opening (
throw SyntaxError("Missing '('", tokens.back().pos); throw SyntaxError(ErrorType::ExceptedLParen, tokens.back().pos);
tokens.pop_back(); tokens.pop_back();
ParseReturn ret1; ParseReturn ret1;
@ -283,7 +283,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
int nb_tok = ret1.tokens.size(); // First ; int nb_tok = ret1.tokens.size(); // First ;
if (nb_tok == 0 || ret1.tokens.back().type != TokenType::Semicolon) if (nb_tok == 0 || ret1.tokens.back().type != TokenType::Semicolon)
throw SyntaxError( throw SyntaxError(
"Expected ';'", ErrorType::ExpectedSemicolon,
nb_tok == 0 ? tokens.back().pos : ret1.tokens.back().pos nb_tok == 0 ? tokens.back().pos : ret1.tokens.back().pos
); );
tokens = ret1.tokens; tokens = ret1.tokens;
@ -302,7 +302,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
nb_tok = ret2.tokens.size(); // Second ; nb_tok = ret2.tokens.size(); // Second ;
if (nb_tok == 0 || ret2.tokens.back().type != TokenType::Semicolon) if (nb_tok == 0 || ret2.tokens.back().type != TokenType::Semicolon)
throw SyntaxError( throw SyntaxError(
"Expected ';'", ErrorType::ExpectedSemicolon,
nb_tok == 0 ? tokens.back().pos : ret2.tokens.back().pos nb_tok == 0 ? tokens.back().pos : ret2.tokens.back().pos
); );
tokens = ret2.tokens; tokens = ret2.tokens;
@ -321,7 +321,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
nb_tok = ret3.tokens.size(); // Closing ) nb_tok = ret3.tokens.size(); // Closing )
if (nb_tok == 0 || ret3.tokens.back().type != TokenType::RParenthese) if (nb_tok == 0 || ret3.tokens.back().type != TokenType::RParenthese)
throw SyntaxError( throw SyntaxError(
"Missing ')'", ErrorType::ExpectedRParen,
nb_tok == 0 ? tokens.back().pos : ret3.tokens.back().pos nb_tok == 0 ? tokens.back().pos : ret3.tokens.back().pos
); );
tokens = ret3.tokens; tokens = ret3.tokens;
@ -351,14 +351,14 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.back().type != TokenType::RCurlyBracket tokens.back().type != TokenType::RCurlyBracket
) )
throw SyntaxError( throw SyntaxError(
"Invalid Syntax. Missing ';' ?", ErrorType::InvalidSyntax,
tokens.back().pos tokens.back().pos
); );
int nb_tok = ret.tokens.size(); int nb_tok = ret.tokens.size();
if (nb_tok == 0 || ret.tokens.back().type != TokenType::RCurlyBracket) if (nb_tok == 0 || ret.tokens.back().type != TokenType::RCurlyBracket)
throw SyntaxError( throw SyntaxError(
"Missing '}'", ErrorType::ExpectedRCurlyBracket,
nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos nb_tok == 0 ? tokens.back().pos : ret.tokens.back().pos
); );
@ -800,7 +800,7 @@ ParseReturn parse_val(vector<Token> tokens) {
tokens=ret.tokens; tokens=ret.tokens;
if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese) if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese)
throw SyntaxError("Missing ')'", tokens.back().pos); throw SyntaxError(ErrorType::ExpectedRParen, tokens.back().pos);
tokens.pop_back(); tokens.pop_back();

View File

@ -259,7 +259,7 @@ vector<Token> tokenize(vector<string> input, int initial_line) {
continue; continue;
} }
throw SyntaxError("Unknown token", pos); throw SyntaxError(ErrorType::UnknownToken, pos);
} }
} }