Parser: Add while & for
This commit is contained in:
parent
5925582de8
commit
a693258d77
@ -36,6 +36,8 @@ Statement ->
|
|||||||
| { Prog }
|
| { Prog }
|
||||||
| If (Expr) Instruction
|
| If (Expr) Instruction
|
||||||
| If (Expr) Instruction Else Instruction
|
| If (Expr) Instruction Else Instruction
|
||||||
|
| While (Expr) Instruction
|
||||||
|
| For (Expr | ExprStatement; Expr; Expr) Instruction
|
||||||
|
|
||||||
ExprStatement ->
|
ExprStatement ->
|
||||||
| Type ParIdentifier = Expr // AssignedDeclaration
|
| Type ParIdentifier = Expr // AssignedDeclaration
|
||||||
@ -114,6 +116,8 @@ enum class NodeType {
|
|||||||
RDecr, // -> ParIdentifier--
|
RDecr, // -> ParIdentifier--
|
||||||
If, // -> If (Expr) Instruction
|
If, // -> If (Expr) Instruction
|
||||||
IfElse, // -> If (Expr) Instruction Else Instruction
|
IfElse, // -> If (Expr) Instruction Else Instruction
|
||||||
|
For, // -> For (Expr) Instruction
|
||||||
|
While, // -> While (Expr/ ExprStatement; Expr; Expr) Instruction
|
||||||
Bloc, // -> { Prog }
|
Bloc, // -> { Prog }
|
||||||
Lt, // -> Sum < Comp
|
Lt, // -> Sum < Comp
|
||||||
Gt, // -> Sum > Comp
|
Gt, // -> Sum > Comp
|
||||||
|
@ -16,7 +16,7 @@ CodePosition null_pos = {
|
|||||||
const char* _node_names[] = {
|
const char* _node_names[] = {
|
||||||
"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod",
|
"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod",
|
||||||
"UnaryMinus", "UnaryPlus", "Neg", "Assignment", "LIncr", "RIncr", "LDecr", "RDecr", "If", "IfElse",
|
"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) {
|
void _debug_print_tree(const Node& node, int depth, const string& prefix) {
|
||||||
if (holds_alternative<InnerNode>(node)) {
|
if (holds_alternative<InnerNode>(node)) {
|
||||||
@ -168,13 +168,26 @@ ParseReturn parse_instruction(vector<Token> tokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ParseReturn parse_statement(vector<Token> tokens) {
|
ParseReturn parse_statement(vector<Token> tokens) {
|
||||||
if (tokens.size() < 2) // 'If' / 'For' '(' at least
|
if (tokens.size() < 2)
|
||||||
throw ParseException();
|
throw ParseException();
|
||||||
|
|
||||||
switch (tokens.back().type) {
|
switch (tokens.back().type) {
|
||||||
|
case TokenType::While:
|
||||||
case TokenType::If: {
|
case TokenType::If: {
|
||||||
CodePosition pos = tokens.back().pos;
|
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();
|
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("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
|
if (tokens.size() == 0 || tokens.back().type != TokenType::Else) { //* -> If (Expr) Instruction
|
||||||
InnerNode node = {
|
InnerNode node = {
|
||||||
.type=NodeType::If,
|
.type=type,
|
||||||
.children={expr, instruction1},
|
.children={expr, instruction1},
|
||||||
.pos=pos
|
.pos=pos
|
||||||
};
|
};
|
||||||
@ -240,6 +253,65 @@ ParseReturn parse_statement(vector<Token> tokens) {
|
|||||||
.tokens=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: {
|
case TokenType::LCurlyBracket: {
|
||||||
CodePosition pos = tokens.back().pos;
|
CodePosition pos = tokens.back().pos;
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
|
Loading…
Reference in New Issue
Block a user