Add parser.cpp
This commit is contained in:
parent
97f82b7307
commit
a8e6a4552b
326
src/parser.cpp
Normal file
326
src/parser.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
#include "include/colors.h"
|
||||
#include "include/parser.h"
|
||||
|
||||
|
||||
Node parse(vector<Token> 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<Token> 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<Node> 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<Token> tokens) {
|
||||
(void)tokens;
|
||||
// Aucune règle
|
||||
throw new ParseException;
|
||||
}
|
||||
|
||||
ParseReturn parse_expr_statement(vector<Token> 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<Token> 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<Token> 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<Token> 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<Token> 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user