Parser: Add while & for
This commit is contained in:
parent
5925582de8
commit
a693258d77
@ -36,6 +36,8 @@ Statement ->
|
||||
| { Prog }
|
||||
| If (Expr) Instruction
|
||||
| If (Expr) Instruction Else Instruction
|
||||
| While (Expr) Instruction
|
||||
| For (Expr | ExprStatement; Expr; Expr) Instruction
|
||||
|
||||
ExprStatement ->
|
||||
| Type ParIdentifier = Expr // AssignedDeclaration
|
||||
@ -114,6 +116,8 @@ enum class NodeType {
|
||||
RDecr, // -> ParIdentifier--
|
||||
If, // -> If (Expr) Instruction
|
||||
IfElse, // -> If (Expr) Instruction Else Instruction
|
||||
For, // -> For (Expr) Instruction
|
||||
While, // -> While (Expr/ ExprStatement; Expr; Expr) Instruction
|
||||
Bloc, // -> { Prog }
|
||||
Lt, // -> Sum < Comp
|
||||
Gt, // -> Sum > Comp
|
||||
|
@ -16,7 +16,7 @@ CodePosition null_pos = {
|
||||
const char* _node_names[] = {
|
||||
"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod",
|
||||
"UnaryMinus", "UnaryPlus", "Neg", "Assignment", "LIncr", "RIncr", "LDecr", "RDecr", "If", "IfElse",
|
||||
"Bloc", "Lt", "Gt", "Leq", "Geq", "Eq", "Neq", "Land", "Lor"
|
||||
"For", "While", "Bloc", "Lt", "Gt", "Leq", "Geq", "Eq", "Neq", "Land", "Lor"
|
||||
};
|
||||
void _debug_print_tree(const Node& node, int depth, const string& prefix) {
|
||||
if (holds_alternative<InnerNode>(node)) {
|
||||
@ -168,13 +168,26 @@ ParseReturn parse_instruction(vector<Token> tokens) {
|
||||
}
|
||||
|
||||
ParseReturn parse_statement(vector<Token> tokens) {
|
||||
if (tokens.size() < 2) // 'If' / 'For' '(' at least
|
||||
if (tokens.size() < 2)
|
||||
throw ParseException();
|
||||
|
||||
switch (tokens.back().type) {
|
||||
case TokenType::While:
|
||||
case TokenType::If: {
|
||||
CodePosition pos = tokens.back().pos;
|
||||
|
||||
NodeType type;
|
||||
switch (tokens.back().type) {
|
||||
case TokenType::If:
|
||||
type = NodeType::If;
|
||||
break;
|
||||
case TokenType::While:
|
||||
type = NodeType::While;
|
||||
break;
|
||||
default:
|
||||
break; // Impossible
|
||||
}
|
||||
|
||||
tokens.pop_back();
|
||||
if (tokens.back().type != TokenType::LParenthese) // Opening (
|
||||
throw SyntaxError("Missing '('", tokens.back().pos);
|
||||
@ -215,7 +228,7 @@ ParseReturn parse_statement(vector<Token> tokens) {
|
||||
|
||||
if (tokens.size() == 0 || tokens.back().type != TokenType::Else) { //* -> If (Expr) Instruction
|
||||
InnerNode node = {
|
||||
.type=NodeType::If,
|
||||
.type=type,
|
||||
.children={expr, instruction1},
|
||||
.pos=pos
|
||||
};
|
||||
@ -240,6 +253,65 @@ ParseReturn parse_statement(vector<Token> tokens) {
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
case TokenType::For: {
|
||||
CodePosition pos = tokens.back().pos;
|
||||
tokens.pop_back();
|
||||
|
||||
if (tokens.back().type != TokenType::LParenthese) // Opening (
|
||||
throw SyntaxError("Missing '('", tokens.back().pos);
|
||||
tokens.pop_back();
|
||||
|
||||
ParseReturn ret1;
|
||||
try {
|
||||
ret1 = parse_expr_statement(tokens);
|
||||
} catch (const ParseException& pex) {
|
||||
ret1 = parse_expr(tokens);
|
||||
}
|
||||
|
||||
int nb_tok = ret1.tokens.size(); // First ;
|
||||
if (nb_tok == 0 || ret1.tokens.back().type != TokenType::Semicolon)
|
||||
throw SyntaxError(
|
||||
"Expected ';'",
|
||||
nb_tok == 0 ? tokens.back().pos : ret1.tokens.back().pos
|
||||
);
|
||||
tokens = ret1.tokens;
|
||||
tokens.pop_back();
|
||||
|
||||
ParseReturn ret2 = parse_expr(tokens);
|
||||
|
||||
nb_tok = ret2.tokens.size(); // Second ;
|
||||
if (nb_tok == 0 || ret2.tokens.back().type != TokenType::Semicolon)
|
||||
throw SyntaxError(
|
||||
"Expected ';'",
|
||||
nb_tok == 0 ? tokens.back().pos : ret2.tokens.back().pos
|
||||
);
|
||||
tokens = ret2.tokens;
|
||||
tokens.pop_back();
|
||||
|
||||
ParseReturn ret3 = parse_expr(tokens);
|
||||
|
||||
nb_tok = ret3.tokens.size(); // Closing )
|
||||
if (nb_tok == 0 || ret3.tokens.back().type != TokenType::RParenthese)
|
||||
throw SyntaxError(
|
||||
"Missing ')'",
|
||||
nb_tok == 0 ? tokens.back().pos : ret3.tokens.back().pos
|
||||
);
|
||||
tokens = ret3.tokens;
|
||||
tokens.pop_back();
|
||||
|
||||
ParseReturn ret_instruction = parse_instruction(tokens);
|
||||
tokens = ret_instruction.tokens;
|
||||
|
||||
InnerNode node = {
|
||||
.type=NodeType::For,
|
||||
.children={ret1.node, ret2.node, ret3.node, ret_instruction.node},
|
||||
.pos=pos
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
case TokenType::LCurlyBracket: {
|
||||
CodePosition pos = tokens.back().pos;
|
||||
tokens.pop_back();
|
||||
|
Loading…
Reference in New Issue
Block a user