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