Add parser.cpp

This commit is contained in:
augustin64 2023-11-10 17:27:54 +01:00
parent 97f82b7307
commit a8e6a4552b

326
src/parser.cpp Normal file
View 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;
}
}