diff --git a/src/parser.cpp b/src/parser.cpp new file mode 100644 index 0000000..57238f6 --- /dev/null +++ b/src/parser.cpp @@ -0,0 +1,326 @@ +#include +#include +#include +using namespace std; + +#include "include/colors.h" +#include "include/parser.h" + + +Node parse(vector tokens) { + reverse(tokens.begin(), tokens.end()); + + if (tokens.size() == 0) + throw new ParseException; + + + // At least 1 instruction + ParseReturn ret = parse_instruction(tokens); + tokens = ret.tokens; + + Node node = ret.node; + + while (tokens.size() != 0) { + ParseReturn ret = parse_instruction(tokens); + tokens = ret.tokens; + + InnerNode new_node = { + .type=NodeType::Prog, + .children={node, ret.node} + }; + node = new_node; + } + + return node; +} + +ParseReturn parse_instruction(vector tokens) { + try { //* Instruction -> Statement + ParseReturn ret = parse_statement(tokens); + + return ret; + } + catch (const ParseException& pex) { + try { //* Instruction -> ExprStatement; + ParseReturn ret = parse_expr_statement(tokens); + + tokens = ret.tokens; + + if (tokens.back().type != TokenType::Semicolon) + throw new ParseException; + + return { + .node=ret.node, + .tokens=tokens + }; + } + catch (const ParseException& pex) { + try { //* Instruction -> Expr; + ParseReturn ret = parse_expr(tokens); + tokens = ret.tokens; + + if (tokens.size() < 1 || tokens.back().type != TokenType::Semicolon) + throw new ParseException; + + return { + .node=ret.node, + .tokens=tokens + }; + } + catch (const ParseException& pex) { //* Instruction -> ; + if (tokens.size() < 1 || tokens.back().type != TokenType::Semicolon) + throw new ParseException; + + vector children; + InnerNode epsilon_node = { + .type=NodeType::Epsilon, + .children=children + }; + tokens.pop_back(); // On enlève le ';' de la liste de tokens + + return { + .node=epsilon_node, + .tokens=tokens + }; + } + } + } +} + +ParseReturn parse_statement(vector tokens) { + (void)tokens; + // Aucune règle + throw new ParseException; +} + +ParseReturn parse_expr_statement(vector tokens) { + if (tokens.size() < 1 || tokens.back().type != TokenType::Type) + throw new ParseException; + + Token type = tokens.back(); + tokens.pop_back(); + + if (tokens.size() < 1 || tokens.back().type != TokenType::Identifier) + throw new ParseException; + + Token identifier = tokens.back(); + tokens.pop_back(); + + //* ExprStatement -> Type Identifier + if (tokens.size() < 1 || tokens.back().type != TokenType::Equal) { + InnerNode node = { + .type=NodeType::Declaration, + .children={type, identifier} + }; + return { + .node=node, + .tokens=tokens + }; + } + + //* ExprStatement -> Type Identifier = Expr + // On retire le '=' + tokens.pop_back(); + + ParseReturn ret = parse_expr(tokens); + + InnerNode node = { + .type=NodeType::Declaration, + .children={type, identifier, ret.node} + }; + return { + .node=node, + .tokens=ret.tokens + }; +} + +ParseReturn parse_expr(vector tokens) { + if (tokens.size() == 0) + throw new ParseException; + + // At least 1 T + ParseReturn ret = parse_t(tokens); + tokens = ret.tokens; + + Node node = ret.node; + + //* We construct a tree + while (tokens.size() != 0) { + try { + ParseReturn ret = parse_t(tokens); + tokens = ret.tokens; + } catch (const ParseException& pex) { + return { + .node=node, + .tokens=tokens + }; + } + + if (tokens.size() != 0) { + if (tokens.back().type == TokenType::Plus) { + InnerNode new_node = { + .type=NodeType::Plus, + .children={node, ret.node} + }; + node = new_node; + } else if (tokens.back().type == TokenType::Minus) { + InnerNode new_node = { + .type=NodeType::Minus, + .children={node, ret.node} + }; + node = new_node; + } + } + } + + return { + .node=node, + .tokens=tokens + }; +} + +ParseReturn parse_t(vector tokens) { + if (tokens.size() == 0) + throw new ParseException; + + + // At least 1 U + ParseReturn ret = parse_u(tokens); + tokens = ret.tokens; + + Node node = ret.node; + + //* We construct a tree + while (tokens.size() != 0) { + try { + ParseReturn ret = parse_u(tokens); + tokens = ret.tokens; + } catch (const ParseException& pex) { + return { + .node=node, + .tokens=tokens + }; + } + + if (tokens.size() != 0) { + if (tokens.back().type == TokenType::Star) { + InnerNode new_node = { + .type=NodeType::Mult, + .children={node, ret.node} + }; + node = new_node; + } else if (tokens.back().type == TokenType::Slash) { + InnerNode new_node = { + .type=NodeType::Div, + .children={node, ret.node} + }; + node = new_node; + } else if (tokens.back().type == TokenType::Percent) { + InnerNode new_node = { + .type=NodeType::Mod, + .children={node, ret.node} + }; + node = new_node; + } + } + } + + return { + .node=node, + .tokens=tokens + }; +} + +ParseReturn parse_u(vector tokens) { + if (tokens.size() > 0 && tokens.back().type == TokenType::Minus) { //* U -> - U + tokens.pop_back(); + + ParseReturn ret = parse_u(tokens); + + InnerNode node = { + .type=NodeType::UnaryMinus, + .children={ ret.node } + }; + return { + .node=node, + .tokens=ret.tokens + }; + } + + if (tokens.size() > 0 && tokens.back().type == TokenType::Plus) { //* U -> + U + tokens.pop_back(); + + ParseReturn ret = parse_u(tokens); + + InnerNode node = { + .type=NodeType::UnaryPlus, + .children={ ret.node } + }; + return { + .node=node, + .tokens=ret.tokens + }; + } + + //* U -> F + return parse_f(tokens); +} + +ParseReturn parse_f(vector tokens) { + if (tokens.size() == 0) + throw new ParseException; + + switch (tokens.back().type) { + case TokenType::Number: { //* U -> Number + Token number = tokens.back(); + tokens.pop_back(); + return { + .node=number, + .tokens=tokens + };; + } + case TokenType::LParenthese: { //* U -> Identifier + tokens.pop_back(); + ParseReturn ret = parse_expr(tokens); + tokens=ret.tokens; + + if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese) + throw new ParseException; + + tokens.pop_back(); + InnerNode node = { + .type=NodeType::Parenthesis, + .children={ ret.node } + }; + return { + .node=node, + .tokens=tokens + }; + } + case TokenType::Identifier: { //* U -> Identifier... + Token identifier = tokens.back(); + tokens.pop_back(); + + if (tokens.size() > 0 && tokens.back().type == TokenType::Equal) { //* U -> Identifier = Expr + tokens.pop_back(); + ParseReturn ret = parse_expr(tokens); + + InnerNode node = { + .type = NodeType::Assignment, + .children = { identifier, ret.node } + }; + return { + .node=node, + .tokens=ret.tokens + }; + } + + return { //* U -> Identifier + .node=identifier, + .tokens=tokens + }; + } + default: + throw new ParseException; + } +} \ No newline at end of file