Add functions parsing
This commit is contained in:
parent
0759050fef
commit
91b398dbe9
@ -264,6 +264,8 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
||||
analyze(node.children[0], memory);
|
||||
return analyze(node.children[1], memory);
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
throw exception();
|
||||
|
@ -16,6 +16,7 @@ string UserError::get_message(void) const {
|
||||
case ErrorType::InvalidSyntax: return "Invalid syntax";
|
||||
case ErrorType::ExceptedLParen: return "Expected '(";
|
||||
case ErrorType::ExpectedRParen: return "Expected ')'";
|
||||
case ErrorType::ExpectedLCurlyBracket: return "Expected '{'";
|
||||
case ErrorType::ExpectedRCurlyBracket: return "Expected '}'";
|
||||
case ErrorType::ExpectedSemicolon: return "Expected ';'";
|
||||
case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration";
|
||||
|
@ -22,6 +22,7 @@ enum class ErrorType {
|
||||
InvalidSyntax,
|
||||
ExceptedLParen,
|
||||
ExpectedRParen,
|
||||
ExpectedLCurlyBracket,
|
||||
ExpectedRCurlyBracket,
|
||||
ExpectedSemicolon,
|
||||
DependentDeclaration,
|
||||
|
@ -78,6 +78,13 @@ ParseReturn parse_val(vector<Token> tokens);
|
||||
*/
|
||||
ParseReturn parse_par_identifier(vector<Token> tokens);
|
||||
|
||||
/**
|
||||
* Parse the arguments of a function
|
||||
* Type1 Identifier1, Type2 Identifier2
|
||||
* and returns it as a node with Declaration as children
|
||||
*/
|
||||
ParseReturn parse_args(vector<Token> tokens);
|
||||
|
||||
/**
|
||||
* Prints a tree for debugging it
|
||||
*/
|
||||
|
@ -63,11 +63,16 @@ Statement ->
|
||||
| For (Expr | ExprStatement; Expr; Expr) Instruction
|
||||
| Continue ;
|
||||
| Break ;
|
||||
| Return ; | Return Expr ;
|
||||
| Type ParIdentifier ( Args ) ;
|
||||
| Type ParIdentifier ( Args ) { Prog }
|
||||
|
||||
ExprStatement ->
|
||||
ExprStatement ->
|
||||
| Type ParIdentifier = Expr // AssignedDeclaration
|
||||
| Type ParIdentifier // Declaration
|
||||
|
||||
Args -> Type ParIdentifier, Args | Type ParIdentifier | void
|
||||
|
||||
|
||||
Expr -> Comp, Expr | Comp
|
||||
|
||||
@ -111,6 +116,7 @@ Val ->
|
||||
| ParIdentifier // This makes the grammar ambiguous but simpler to parse
|
||||
|
||||
| (Expr)
|
||||
| ParIdentifier ( Expr ) // FunctionCall
|
||||
|
||||
ParIdentifier ->
|
||||
| Identifier
|
||||
@ -152,7 +158,12 @@ enum class NodeType {
|
||||
Neq, // -> Sum != Comp
|
||||
Land, // -> Sum && Comp
|
||||
Lor, // -> Sum || Comp
|
||||
Comma // -> Comp, Expr
|
||||
Comma, // -> Comp, Expr
|
||||
FunctionPrototype, // -> Type ParIdentifier ( Args ) ;
|
||||
FunctionDeclaration, // -> Type ParIdentifier ( Args ) { Prog }
|
||||
FunctionCall, // -> ParIdentifier ( Expr )
|
||||
FunctionArgs, // -> Type ParIdentifier, Args | Type ParIdentifier | void
|
||||
Return, // -> Return ; | Return Expr ;
|
||||
};
|
||||
|
||||
struct InnerNode;
|
||||
|
171
src/parser.cpp
171
src/parser.cpp
@ -17,7 +17,8 @@ CodePosition null_pos = {
|
||||
const char* _debug_ast_node_names[] = {
|
||||
"Prog", "Epsilon", "AssignedDeclaration", "Declaration", "Plus", "Minus", "Mult", "Div", "Mod",
|
||||
"UnaryMinus", "UnaryPlus", "Neg", "Assignment", "LIncr", "RIncr", "LDecr", "RDecr", "If", "IfElse",
|
||||
"For", "While", "Bloc", "Lt", "Gt", "Leq", "Geq", "Eq", "Neq", "Land", "Lor", "Comma"
|
||||
"For", "While", "Bloc", "Lt", "Gt", "Leq", "Geq", "Eq", "Neq", "Land", "Lor", "Comma",
|
||||
"FunctionPrototype", "FunctionDeclaration", "FunctionCall", "FunctionArgs", "Return"
|
||||
};
|
||||
void _debug_print_tree(const Node& node, int depth, const string& prefix) {
|
||||
if (holds_alternative<InnerNode>(node)) {
|
||||
@ -177,6 +178,32 @@ ParseReturn parse_statement(vector<Token> tokens) {
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
case TokenType::Return: {
|
||||
CodePosition pos = tokens.back().pos;
|
||||
tokens.pop_back();
|
||||
|
||||
vector<Node> children;
|
||||
if (tokens.back().type != TokenType::Semicolon) {
|
||||
ParseReturn ret = parse_expr(tokens);
|
||||
tokens = ret.tokens;
|
||||
|
||||
if (tokens.back().type != TokenType::Semicolon)
|
||||
throw SyntaxError(ErrorType::ExpectedSemicolon, tokens.back().pos);
|
||||
|
||||
children = {ret.node};
|
||||
}
|
||||
|
||||
tokens.pop_back();
|
||||
InnerNode node = {
|
||||
.type=NodeType::Return,
|
||||
.children=children,
|
||||
.pos=pos
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
case TokenType::While:
|
||||
case TokenType::If: {
|
||||
CodePosition pos = tokens.back().pos;
|
||||
@ -374,7 +401,79 @@ ParseReturn parse_statement(vector<Token> tokens) {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
case TokenType::Identifier: {
|
||||
//* Type
|
||||
Token type = tokens.back();
|
||||
tokens.pop_back();
|
||||
|
||||
//* ParIdentifier
|
||||
ParseReturn ret = parse_par_identifier(tokens);
|
||||
tokens = ret.tokens;
|
||||
|
||||
if (!holds_alternative<Token>(ret.node))
|
||||
throw ParseException(); // The parsing is incorrect
|
||||
|
||||
Token identifier = get<Token>(ret.node);
|
||||
|
||||
// LPar
|
||||
if (tokens.size() < 1 || tokens.back().type != TokenType::LParenthese)
|
||||
throw ParseException();
|
||||
|
||||
tokens.pop_back();
|
||||
|
||||
//* Args
|
||||
ParseReturn args_ret = parse_args(tokens);
|
||||
|
||||
// RPar
|
||||
if (args_ret.tokens.size() < 1 || args_ret.tokens.back().type != TokenType::RParenthese)
|
||||
throw SyntaxError(ErrorType::ExpectedRParen, tokens.back().pos, {});
|
||||
|
||||
tokens = args_ret.tokens;
|
||||
tokens.pop_back();
|
||||
|
||||
if (tokens.size() < 1)
|
||||
throw SyntaxError(ErrorType::ExpectedSemicolon, identifier.pos, {});
|
||||
|
||||
|
||||
if (tokens.back().type == TokenType::Semicolon) { //* -> Type ParIdentifier ( Args ) ;
|
||||
tokens.pop_back();
|
||||
|
||||
InnerNode node = {
|
||||
.type=NodeType::FunctionPrototype,
|
||||
.children={type, identifier, args_ret.node},
|
||||
.pos=identifier.pos
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
|
||||
//* LCurly
|
||||
if (tokens.size() < 1 || tokens.back().type != TokenType::LCurlyBracket)
|
||||
throw SyntaxError(ErrorType::ExpectedLCurlyBracket, identifier.pos, {});
|
||||
|
||||
tokens.pop_back();
|
||||
|
||||
ParseReturn ret_prog = parse_prog(tokens);
|
||||
tokens = ret_prog.tokens;
|
||||
|
||||
//* RCurly
|
||||
if (tokens.size() < 1 || tokens.back().type != TokenType::RCurlyBracket)
|
||||
throw SyntaxError(ErrorType::ExpectedRCurlyBracket, identifier.pos, {});
|
||||
|
||||
tokens.pop_back();
|
||||
|
||||
InnerNode node = {
|
||||
.type=NodeType::FunctionDeclaration,
|
||||
.children={type, identifier, args_ret.node, ret_prog.node},
|
||||
.pos=identifier.pos
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw ParseException();
|
||||
@ -467,6 +566,52 @@ ParseReturn parse_expr(vector<Token> tokens) {
|
||||
};
|
||||
}
|
||||
|
||||
ParseReturn parse_args(vector<Token> tokens) {
|
||||
vector<Node> nodes;
|
||||
CodePosition pos = tokens.back().pos;
|
||||
|
||||
while (tokens.size() != 0 && tokens.back().type != TokenType::RParenthese) {
|
||||
if (tokens.back().type != TokenType::Identifier)
|
||||
throw ParseException();
|
||||
|
||||
Token type = tokens.back();
|
||||
tokens.pop_back();
|
||||
|
||||
// TODO: if type is void, return
|
||||
|
||||
ParseReturn ret = parse_par_identifier(tokens);
|
||||
tokens = ret.tokens;
|
||||
|
||||
if (!holds_alternative<Token>(ret.node))
|
||||
throw ParseException(); // The parsing is incorrect
|
||||
|
||||
Token identifier = get<Token>(ret.node);
|
||||
|
||||
InnerNode node = {
|
||||
.type=NodeType::Declaration,
|
||||
.children={type, identifier},
|
||||
.pos=identifier.pos
|
||||
};
|
||||
nodes.push_back(node);
|
||||
|
||||
if (tokens.back().type == TokenType::Comma) {
|
||||
tokens.pop_back();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InnerNode node = {
|
||||
.type=NodeType::FunctionArgs,
|
||||
.children=nodes,
|
||||
.pos=pos
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=tokens
|
||||
};
|
||||
}
|
||||
|
||||
ParseReturn parse_comp(vector<Token> tokens) {
|
||||
if (tokens.size() == 0)
|
||||
throw ParseException();
|
||||
@ -769,6 +914,30 @@ ParseReturn parse_val(vector<Token> tokens) {
|
||||
.tokens=ret.tokens
|
||||
};
|
||||
}
|
||||
case TokenType::LParenthese: {
|
||||
ret.tokens.pop_back();
|
||||
|
||||
ParseReturn ret_expr = parse_expr(ret.tokens);
|
||||
|
||||
if (ret_expr.tokens.size() < 1 || ret_expr.tokens.back().type != TokenType::RParenthese)
|
||||
throw SyntaxError(
|
||||
ErrorType::ExpectedRParen,
|
||||
ret_expr.tokens.size() < 1 ? ret.tokens.back().pos : ret_expr.tokens.back().pos,
|
||||
{}
|
||||
);
|
||||
|
||||
ret_expr.tokens.pop_back();
|
||||
|
||||
InnerNode node = {
|
||||
.type = NodeType::FunctionCall,
|
||||
.children = { ret.node, ret_expr.node },
|
||||
.pos=get_node_pos(ret.node)
|
||||
};
|
||||
return {
|
||||
.node=node,
|
||||
.tokens=ret_expr.tokens
|
||||
};
|
||||
}
|
||||
case TokenType::Equal: { //* Val -> ParIdentifier = (Expr)
|
||||
ret.tokens.pop_back();
|
||||
ParseReturn ret_expr = parse_expr(ret.tokens);
|
||||
|
Loading…
Reference in New Issue
Block a user