Added ParIdentifier, ++, --
(tokens & ast for now)
This commit is contained in:
parent
0b79ee7822
commit
fcd0c34885
@ -14,8 +14,8 @@ Instruction -> Statement | ExprStatement; | Expr; | ;
|
|||||||
|
|
||||||
Statement -> // Rien pour l'instant, mais "for", "if" etc
|
Statement -> // Rien pour l'instant, mais "for", "if" etc
|
||||||
ExprStatement ->
|
ExprStatement ->
|
||||||
| Type Identifier = Expr // AssignedDeclaration
|
| Type ParIdentifier = Expr // AssignedDeclaration
|
||||||
| Type Identifier // Declaration
|
| Type ParIdentifier // Declaration
|
||||||
|
|
||||||
|
|
||||||
Expr ->
|
Expr ->
|
||||||
@ -35,10 +35,21 @@ U ->
|
|||||||
| + U
|
| + U
|
||||||
|
|
||||||
F ->
|
F ->
|
||||||
| (Expr)
|
|
||||||
| Identifier
|
|
||||||
| Number
|
| Number
|
||||||
| Identifier = Expr // Assignment
|
|
||||||
|
| ++ParIdentifier
|
||||||
|
| --ParIdentifier
|
||||||
|
|
||||||
|
| ParIdentifier = Expr // Assignment
|
||||||
|
| ParIdentifier++
|
||||||
|
| ParIdentifier--
|
||||||
|
| ParIdentifier // This makes the grammar ambiguous but simpler to parse
|
||||||
|
|
||||||
|
| (Expr)
|
||||||
|
|
||||||
|
ParIdentifier ->
|
||||||
|
| Identifier
|
||||||
|
| (ParIdentifier)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +68,11 @@ enum class NodeType {
|
|||||||
Mod, // -> F % T
|
Mod, // -> F % T
|
||||||
UnaryMinus, // -> -F
|
UnaryMinus, // -> -F
|
||||||
UnaryPlus, // -> +F
|
UnaryPlus, // -> +F
|
||||||
Assignment // -> Identifier = Expr
|
Assignment, // -> Identifier = Expr
|
||||||
|
LIncr, // -> ++ParIdentifier
|
||||||
|
RIncr, // -> ParIdentifier++
|
||||||
|
LDecr, // -> --ParIdentifier
|
||||||
|
RDecr // -> ParIdentifier--
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InnerNode;
|
struct InnerNode;
|
||||||
@ -142,6 +157,12 @@ ParseReturn parse_u(vector<Token> tokens);
|
|||||||
*/
|
*/
|
||||||
ParseReturn parse_f(vector<Token> tokens);
|
ParseReturn parse_f(vector<Token> tokens);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse something derivated from ParIdentifier
|
||||||
|
* (An identifier with 0+ parentheses around it)
|
||||||
|
*/
|
||||||
|
ParseReturn parse_par_identifier(vector<Token> tokens);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints a tree for debugging it
|
* Prints a tree for debugging it
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
enum class TokenType { Type, Identifier, Int, Plus, Minus, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese };
|
enum class TokenType { Type, Identifier, Int, Plus, Minus, DoublePlus, DoubleMinus, Star, Slash, Percent, Equal, Semicolon, LParenthese, RParenthese };
|
||||||
enum class Type { Int };
|
enum class Type { Int };
|
||||||
|
|
||||||
using TokenData = variant<int, string, Type>;
|
using TokenData = variant<int, string, Type>;
|
||||||
|
154
src/parser.cpp
154
src/parser.cpp
@ -7,7 +7,7 @@ using namespace std;
|
|||||||
#include "include/parser.h"
|
#include "include/parser.h"
|
||||||
|
|
||||||
|
|
||||||
const char* _node_names[] = {"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod", "UnaryMinus", "UnaryPlus", "Assignment"};
|
const char* _node_names[] = {"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod", "UnaryMinus", "UnaryPlus", "Assignment", "LIncr", "RIncr", "LDecr", "RDecr"};
|
||||||
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)) {
|
||||||
const InnerNode& innerNode = get<InnerNode>(node);
|
const InnerNode& innerNode = get<InnerNode>(node);
|
||||||
@ -135,11 +135,13 @@ ParseReturn parse_expr_statement(vector<Token> tokens) {
|
|||||||
Token type = tokens.back();
|
Token type = tokens.back();
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
|
|
||||||
if (tokens.size() < 1 || tokens.back().type != TokenType::Identifier)
|
ParseReturn ret = parse_par_identifier(tokens);
|
||||||
throw ParseException();
|
tokens = ret.tokens;
|
||||||
|
|
||||||
Token identifier = tokens.back();
|
if (!holds_alternative<Token>(ret.node))
|
||||||
tokens.pop_back();
|
throw ParseException(); // The parsing is incorrect
|
||||||
|
|
||||||
|
Token identifier = get<Token>(ret.node);
|
||||||
|
|
||||||
//* ExprStatement -> Type Identifier
|
//* ExprStatement -> Type Identifier
|
||||||
if (tokens.size() < 1 || tokens.back().type != TokenType::Equal) {
|
if (tokens.size() < 1 || tokens.back().type != TokenType::Equal) {
|
||||||
@ -157,7 +159,7 @@ ParseReturn parse_expr_statement(vector<Token> tokens) {
|
|||||||
// On retire le '='
|
// On retire le '='
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
|
|
||||||
ParseReturn ret = parse_expr(tokens);
|
ret = parse_expr(tokens);
|
||||||
|
|
||||||
InnerNode node = {
|
InnerNode node = {
|
||||||
.type=NodeType::AssignedDeclaration,
|
.type=NodeType::AssignedDeclaration,
|
||||||
@ -325,7 +327,7 @@ ParseReturn parse_f(vector<Token> tokens) {
|
|||||||
throw ParseException();
|
throw ParseException();
|
||||||
|
|
||||||
switch (tokens.back().type) {
|
switch (tokens.back().type) {
|
||||||
case TokenType::Int: { //* U -> Number
|
case TokenType::Int: { //* F -> Number
|
||||||
Token number = tokens.back();
|
Token number = tokens.back();
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
return {
|
return {
|
||||||
@ -333,45 +335,131 @@ ParseReturn parse_f(vector<Token> tokens) {
|
|||||||
.tokens=tokens
|
.tokens=tokens
|
||||||
};;
|
};;
|
||||||
}
|
}
|
||||||
case TokenType::LParenthese: { //* U -> Identifier
|
case TokenType::DoublePlus: { //* F -> ++ParIdentifier
|
||||||
tokens.pop_back();
|
|
||||||
ParseReturn ret = parse_expr(tokens);
|
|
||||||
tokens=ret.tokens;
|
|
||||||
|
|
||||||
if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese)
|
|
||||||
throw SyntaxError("Missing ')'");
|
|
||||||
|
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
|
ParseReturn ret = parse_par_identifier(tokens);
|
||||||
|
|
||||||
|
InnerNode node = {
|
||||||
|
.type = NodeType::LIncr,
|
||||||
|
.children = { ret.node }
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
.node=ret.node,
|
.node=node,
|
||||||
.tokens=tokens
|
.tokens=ret.tokens
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case TokenType::Identifier: { //* U -> Identifier...
|
case TokenType::DoubleMinus: { //* F -> --ParIdentifier
|
||||||
Token identifier = tokens.back();
|
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
|
ParseReturn ret = parse_par_identifier(tokens);
|
||||||
|
|
||||||
|
InnerNode node = {
|
||||||
|
.type = NodeType::LDecr,
|
||||||
|
.children = { ret.node }
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
.node=node,
|
||||||
|
.tokens=ret.tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
try { //* F -> ParIdentifier...
|
||||||
|
ParseReturn ret = parse_par_identifier(tokens);
|
||||||
|
|
||||||
|
if (ret.tokens.size() >= 1) {
|
||||||
|
switch (ret.tokens.back().type){
|
||||||
|
case TokenType::DoublePlus: { //* F -> ParIdentifier++
|
||||||
|
ret.tokens.pop_back();
|
||||||
|
InnerNode node = {
|
||||||
|
.type = NodeType::RIncr,
|
||||||
|
.children = { ret.node }
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
.node=node,
|
||||||
|
.tokens=ret.tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case TokenType::DoubleMinus: { //* F -> ParIdentifier--
|
||||||
|
ret.tokens.pop_back();
|
||||||
|
InnerNode node = {
|
||||||
|
.type = NodeType::RDecr,
|
||||||
|
.children = { ret.node }
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
.node=node,
|
||||||
|
.tokens=ret.tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case TokenType::Equal: { //* F -> ParIdentifier = (Expr)
|
||||||
|
ret.tokens.pop_back();
|
||||||
|
ParseReturn ret_expr = parse_expr(ret.tokens);
|
||||||
|
|
||||||
|
InnerNode node = {
|
||||||
|
.type = NodeType::Assignment,
|
||||||
|
.children = { ret.node, ret_expr.node }
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
.node=node,
|
||||||
|
.tokens=ret_expr.tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//* F -> ParIdentifier
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
} catch (const ParseException& pex) { //* F -> (Expr)
|
||||||
|
if (tokens.back().type != TokenType::LParenthese)
|
||||||
|
throw ParseException();
|
||||||
|
|
||||||
if (tokens.size() > 0 && tokens.back().type == TokenType::Equal) { //* U -> Identifier = Expr
|
|
||||||
tokens.pop_back();
|
tokens.pop_back();
|
||||||
ParseReturn ret = parse_expr(tokens);
|
ParseReturn ret = parse_expr(tokens);
|
||||||
|
tokens=ret.tokens;
|
||||||
|
|
||||||
|
if (tokens.size() < 1 || tokens.back().type != TokenType::RParenthese)
|
||||||
|
throw SyntaxError("Missing ')'");
|
||||||
|
|
||||||
|
tokens.pop_back();
|
||||||
|
|
||||||
InnerNode node = {
|
|
||||||
.type = NodeType::Assignment,
|
|
||||||
.children = { identifier, ret.node }
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
.node=node,
|
.node=ret.node,
|
||||||
.tokens=ret.tokens
|
.tokens=tokens
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { //* U -> Identifier
|
|
||||||
.node=identifier,
|
|
||||||
.tokens=tokens
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
throw ParseException();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ParseReturn parse_par_identifier(vector<Token> tokens) {
|
||||||
|
if (tokens.size() < 1)
|
||||||
|
throw ParseException();
|
||||||
|
|
||||||
|
if (tokens.back().type == TokenType::Identifier) {
|
||||||
|
Token identifier = tokens.back();
|
||||||
|
tokens.pop_back();
|
||||||
|
|
||||||
|
return { //* ParIdentifier -> Identifier
|
||||||
|
.node=identifier,
|
||||||
|
.tokens=tokens
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens.back().type != TokenType::LParenthese)
|
||||||
|
throw ParseException();
|
||||||
|
|
||||||
|
tokens.pop_back();
|
||||||
|
ParseReturn ret = parse_par_identifier(tokens);
|
||||||
|
tokens = ret.tokens;
|
||||||
|
|
||||||
|
if (tokens.back().type != TokenType::RParenthese)
|
||||||
|
throw ParseException();
|
||||||
|
|
||||||
|
tokens.pop_back();
|
||||||
|
|
||||||
|
return { //* ParIdentifier -> (ParIdentifier)
|
||||||
|
.node=ret.node,
|
||||||
|
.tokens=tokens
|
||||||
|
};
|
||||||
}
|
}
|
@ -26,6 +26,12 @@ void _debug_print_token(Token token) {
|
|||||||
case TokenType::Minus:
|
case TokenType::Minus:
|
||||||
cout << "-";
|
cout << "-";
|
||||||
break;
|
break;
|
||||||
|
case TokenType::DoublePlus:
|
||||||
|
cout << "++";
|
||||||
|
break;
|
||||||
|
case TokenType::DoubleMinus:
|
||||||
|
cout << "--";
|
||||||
|
break;
|
||||||
case TokenType::Star:
|
case TokenType::Star:
|
||||||
cout << "*";
|
cout << "*";
|
||||||
break;
|
break;
|
||||||
@ -87,6 +93,16 @@ vector<Token> tokenize(string str) {
|
|||||||
tokens.emplace_back(token);
|
tokens.emplace_back(token);
|
||||||
str.erase(0, m.str().length());
|
str.erase(0, m.str().length());
|
||||||
}
|
}
|
||||||
|
else if (str.size() >= 2 && str[0] == '+' && str[1] == '+') {
|
||||||
|
Token token = { .type = TokenType::DoublePlus };
|
||||||
|
tokens.emplace_back(token);
|
||||||
|
str.erase(0, 2);
|
||||||
|
}
|
||||||
|
else if (str.size() >= 2 && str[0] == '-' && str[1] == '-') {
|
||||||
|
Token token = { .type = TokenType::DoubleMinus };
|
||||||
|
tokens.emplace_back(token);
|
||||||
|
str.erase(0, 2);
|
||||||
|
}
|
||||||
else if (str[0] == '+') {
|
else if (str[0] == '+') {
|
||||||
Token token = { .type = TokenType::Plus };
|
Token token = { .type = TokenType::Plus };
|
||||||
tokens.emplace_back(token);
|
tokens.emplace_back(token);
|
||||||
|
Loading…
Reference in New Issue
Block a user