Allow unnamed parameters in function prototype

This commit is contained in:
augustin64 2024-01-04 21:55:17 +01:00
parent 9749b13253
commit aa25c31bcf
5 changed files with 39 additions and 14 deletions

View File

@ -27,6 +27,7 @@ string UserError::get_message(void) const {
case ErrorType::ExpectedRCurlyBracket: return "Expected '}'"; case ErrorType::ExpectedRCurlyBracket: return "Expected '}'";
case ErrorType::ExpectedSemicolon: return "Expected ';'"; case ErrorType::ExpectedSemicolon: return "Expected ';'";
case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration"; case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration";
case ErrorType::NameOmitted: return "Omitting parameter name in a function definition";
// Flow control // Flow control
case ErrorType::BreakNotWithinLoop: return "Break statement not within loop"; case ErrorType::BreakNotWithinLoop: return "Break statement not within loop";

View File

@ -26,6 +26,7 @@ enum class ErrorType {
ExpectedRCurlyBracket, ExpectedRCurlyBracket,
ExpectedSemicolon, ExpectedSemicolon,
DependentDeclaration, DependentDeclaration,
NameOmitted, // int main(int, int) { ... }
// Flow control // Flow control
BreakNotWithinLoop, BreakNotWithinLoop,

View File

@ -3,6 +3,7 @@
#include <vector> #include <vector>
#include <variant> #include <variant>
#include <optional>
#include <stdexcept> #include <stdexcept>
#include "tokenize.h" #include "tokenize.h"
#include "errors.h" #include "errors.h"
@ -88,7 +89,7 @@ ParseReturn parse_par_identifier(vector<Token> tokens);
* Type1 Identifier1, Type2 Identifier2 * Type1 Identifier1, Type2 Identifier2
* and returns it as a node with Declaration as children * and returns it as a node with Declaration as children
*/ */
ParseReturn parse_args(vector<Token> tokens); tuple<ParseReturn, optional<CodePosition>> parse_args(vector<Token> tokens);
/** /**
* Prints a tree for debugging it * Prints a tree for debugging it

View File

@ -18,7 +18,7 @@ void show_help(char* prog_name) {
} }
void parse_args(int argc, char* argv[], bool &print_tokens, bool &print_ast, bool &dump_type_mem, bool &dump_mem, bool &help) { void parse_main_arguments(int argc, char* argv[], bool &print_tokens, bool &print_ast, bool &dump_type_mem, bool &dump_mem, bool &help) {
int i=1; int i=1;
while (i < argc) { while (i < argc) {
char* cur = argv[i]; char* cur = argv[i];
@ -70,7 +70,7 @@ int main(int argc, char* argv[]) {
bool dump_mem = false; bool dump_mem = false;
bool help = false; bool help = false;
parse_args(argc, argv, print_tokens, print_ast, dump_type_mem, dump_mem, help); parse_main_arguments(argc, argv, print_tokens, print_ast, dump_type_mem, dump_mem, help);
if (help) { if (help) {
show_help(argv[0]); show_help(argv[0]);

View File

@ -424,7 +424,9 @@ ParseReturn parse_statement(vector<Token> tokens) {
tokens.pop_back(); tokens.pop_back();
//* Args //* Args
ParseReturn args_ret = parse_args(tokens); tuple<ParseReturn, optional<CodePosition>> args_ret_t = parse_args(tokens);
ParseReturn args_ret = get<0>(args_ret_t);
optional<CodePosition> unnamed = get<1>(args_ret_t); // Contient, s'il existe la position du type du premier argument n'ayant pas de nom
// RPar // RPar
if (args_ret.tokens.size() < 1 || args_ret.tokens.back().type != TokenType::RParenthese) if (args_ret.tokens.size() < 1 || args_ret.tokens.back().type != TokenType::RParenthese)
@ -451,6 +453,9 @@ ParseReturn parse_statement(vector<Token> tokens) {
}; };
} }
if (bool(unnamed))
throw SyntaxError(ErrorType::NameOmitted, unnamed.value(), {});
//* LCurly //* LCurly
if (tokens.size() < 1 || tokens.back().type != TokenType::LCurlyBracket) if (tokens.size() < 1 || tokens.back().type != TokenType::LCurlyBracket)
throw SyntaxError(ErrorType::ExpectedLCurlyBracket, identifier.pos, {}); throw SyntaxError(ErrorType::ExpectedLCurlyBracket, identifier.pos, {});
@ -616,9 +621,10 @@ ParseReturn parse_args_values(vector<Token> tokens) {
}; };
} }
ParseReturn parse_args(vector<Token> tokens) { tuple<ParseReturn, optional<CodePosition>> parse_args(vector<Token> tokens) {
vector<Node> nodes; vector<Node> nodes;
CodePosition pos = tokens.back().pos; CodePosition pos = tokens.back().pos;
optional<CodePosition> unnamed;
while (tokens.size() != 0 && tokens.back().type != TokenType::RParenthese) { while (tokens.size() != 0 && tokens.back().type != TokenType::RParenthese) {
if (tokens.back().type != TokenType::Identifier) if (tokens.back().type != TokenType::Identifier)
@ -629,13 +635,28 @@ ParseReturn parse_args(vector<Token> tokens) {
// TODO: if type is void, return // TODO: if type is void, return
Token identifier;
try {
ParseReturn ret = parse_par_identifier(tokens); ParseReturn ret = parse_par_identifier(tokens);
tokens = ret.tokens; tokens = ret.tokens;
if (!holds_alternative<Token>(ret.node)) if (!holds_alternative<Token>(ret.node))
throw ParseException(); // The parsing is incorrect throw ParseException(); // The parsing is incorrect
Token identifier = get<Token>(ret.node); identifier = get<Token>(ret.node);
} catch (const ParseException &pex) {
if (tokens.back().type == TokenType::Comma || tokens.back().type == TokenType::RParenthese) {
identifier = {
.type=TokenType::Identifier,
.data="",
.pos=null_pos
};
if (!unnamed)
unnamed = type.pos;
} else {
throw ParseException();
}
}
InnerNode node = { InnerNode node = {
.type=NodeType::Declaration, .type=NodeType::Declaration,
@ -651,15 +672,16 @@ ParseReturn parse_args(vector<Token> tokens) {
} }
} }
InnerNode node = { InnerNode inner_node = {
.type=NodeType::FunctionArgs, .type=NodeType::FunctionArgs,
.children=nodes, .children=nodes,
.pos=pos .pos=pos
}; };
return { ParseReturn retval = {
.node=node, .node=inner_node,
.tokens=tokens .tokens=tokens
}; };
return {retval, unnamed};
} }
ParseReturn parse_comp(vector<Token> tokens) { ParseReturn parse_comp(vector<Token> tokens) {