From 7b76b0d88833f032a88779799c32e8ede0dc769e Mon Sep 17 00:00:00 2001 From: William Bell Date: Wed, 4 Jun 2025 23:12:03 +0100 Subject: [PATCH] add declaration with function support --- src/lexer/lex.l | 1 + src/lexer/token.h | 1 + src/parser/assignable/call/call.c | 2 ++ src/parser/declaration/declaration.c | 50 ++++++++++++++++++++++++++-- src/parser/declaration/declaration.h | 5 +-- src/parser/literals/literals.c | 29 ++++++++++++++++ src/parser/literals/literals.h | 10 ++++++ src/parser/parser.c | 34 ++++++++++++++----- src/parser/parser.h | 4 ++- test.ar | 6 ++-- 10 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 src/parser/literals/literals.c create mode 100644 src/parser/literals/literals.h diff --git a/src/lexer/lex.l b/src/lexer/lex.l index c10b76c..ddb33ae 100644 --- a/src/lexer/lex.l +++ b/src/lexer/lex.l @@ -16,6 +16,7 @@ int yywrap(void * unused_param) { %% "." { return TOKEN_DOT; } +"!" { return TOKEN_EXCLAMATION; } "," { return TOKEN_COMMA; } ":" { return TOKEN_COLON; } diff --git a/src/lexer/token.h b/src/lexer/token.h index 3312fc4..7892554 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -71,6 +71,7 @@ typedef enum { TOKEN_DOT, TOKEN_COMMA, TOKEN_COLON, + TOKEN_EXCLAMATION, } TokenType; typedef struct { diff --git a/src/parser/assignable/call/call.c b/src/parser/assignable/call/call.c index 2a594f0..49ea61f 100644 --- a/src/parser/assignable/call/call.c +++ b/src/parser/assignable/call/call.c @@ -34,9 +34,11 @@ ParsedValue *parse_call(char *file, DArray *tokens, size_t *index, break; ParsedValue *parsedValue = parse_token(file, tokens, index, true); darray_push(arg, parsedValue); + free(parsedValue); switch (token->type) { case TOKEN_COMMA: darray_push(args, arg); + free(arg); arg = checked_malloc(sizeof(DArray)); darray_init(arg, sizeof(ParsedValue)); break; diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index 8e542ad..366234f 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -2,11 +2,12 @@ #include "../../lexer/token.h" #include "../../memory.h" #include "../parser.h" +#include "../literals/literals.h" #include #include #include -ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens, +ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; error_if_finished(file, tokens, index); @@ -14,6 +15,8 @@ ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens, ParsedValue * parsedValue = malloc(sizeof(ParsedValue)); ParsedDeclaration * declaration = malloc(sizeof(ParsedDeclaration)); + declaration->is_function = false; + declaration->from = parse_null(); parsedValue->data = declaration; parsedValue->type = AST_DECLARATION; @@ -23,8 +26,51 @@ ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens, exit(EXIT_FAILURE); } declaration->name = strcpy(checked_malloc(sizeof(token->value)), token->value); + (*index)++; - if ((*index) >= tokens->size) return parsedValue; + if ((*index) >= tokens->size) { + return parsedValue; + } token = darray_get(tokens, *index); + if (token->type == TOKEN_LPAREN) { + declaration->is_function = true; + declaration->parameters = checked_malloc(sizeof(DArray)); + darray_init(declaration->parameters, sizeof(char*)); + (*index)++; + error_if_finished(file, tokens, index); + while(true) { + token = darray_get(tokens, *index); + if (token->type != TOKEN_IDENTIFIER) { + fprintf(stderr, "%s:%u:%u error: parameter names need to start with a letter or _, only use letters, digits, or _, and can't be keywords.\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + darray_push(declaration->parameters, strcpy(checked_malloc(sizeof(token->value)), token->value)); + (*index)++; + error_if_finished(file, tokens, index); + token = darray_get(tokens, *index); + if (token->type == TOKEN_RPAREN) { + (*index)++; + error_if_finished(file, tokens, index); + token = darray_get(tokens, *index); + break; + } else if (token->type != TOKEN_COMMA) { + fprintf(stderr, "%s:%u:%u error: expected comma\n", + file, token->line, token->column); + exit(EXIT_FAILURE); + } + (*index)++; + error_if_finished(file, tokens, index); + } + } + if (token->type != TOKEN_ASSIGN) return parsedValue; + + (*index)++; + error_if_finished(file, tokens, index); + + free(declaration->from); + + declaration->from = parse_token(file, tokens, index, true); + return parsedValue; } \ No newline at end of file diff --git a/src/parser/declaration/declaration.h b/src/parser/declaration/declaration.h index 6e9376d..571da4d 100644 --- a/src/parser/declaration/declaration.h +++ b/src/parser/declaration/declaration.h @@ -6,11 +6,12 @@ typedef struct { char * name; bool is_function; - DArray args; // string[] + DArray * parameters; // string[] ParsedValue * from; } ParsedDeclaration; // Function declaration for parsing an identifier -ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens, size_t *index); +ParsedValue *parse_declaration(char *file, DArray *tokens, + size_t *index); #endif // DECLARATION_H \ No newline at end of file diff --git a/src/parser/literals/literals.c b/src/parser/literals/literals.c new file mode 100644 index 0000000..d72bb87 --- /dev/null +++ b/src/parser/literals/literals.c @@ -0,0 +1,29 @@ +#include "literals.h" +#include "../parser.h" +#include +#include "../../memory.h" + +static bool true_value = true; +static bool false_value = false; + +ParsedValue * parse_true(){ + ParsedValue * parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type = AST_BOOLEAN; + parsedValue->data = &true_value; + return parsedValue; +}; + +ParsedValue * parse_false(){ + ParsedValue * parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type = AST_BOOLEAN; + parsedValue->data = &false_value; + return parsedValue; +}; + + +ParsedValue * parse_null(){ + ParsedValue * parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type = AST_NULL; + parsedValue->data = NULL; + return parsedValue; +}; \ No newline at end of file diff --git a/src/parser/literals/literals.h b/src/parser/literals/literals.h new file mode 100644 index 0000000..12a24cf --- /dev/null +++ b/src/parser/literals/literals.h @@ -0,0 +1,10 @@ +#ifndef LITERALS_H +#define LITERALS_H +#include "../parser.h" + +ParsedValue * parse_true(); +ParsedValue * parse_false(); +ParsedValue * parse_null(); + + +#endif // LITERALS_H \ No newline at end of file diff --git a/src/parser/parser.c b/src/parser/parser.c index 7e838f0..cc53d4d 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -3,9 +3,11 @@ #include "../lexer/token.h" #include "assignable/assign/assign.h" #include "assignable/identifier/identifier.h" +#include "declaration/declaration.h" #include "if/if.h" #include "number/number.h" #include "string/string.h" +#include "literals/literals.h" #include #include #include @@ -14,7 +16,7 @@ const char *ValueTypeNames[] = {"string", "assign", "identifier", "number", "if statement", "access", - "call"}; + "call", "declaration", "null", "boolean"}; void error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { @@ -25,11 +27,11 @@ void error_if_finished(char *file, DArray *tokens, size_t *index) { } } -ParsedValue *parse_token(char *file, DArray *tokens, - size_t *index, bool inline_flag) { +ParsedValue *parse_token(char *file, DArray *tokens, size_t *index, + bool inline_flag) { Token *token = darray_get(tokens, *index); - ParsedValue * output = NULL; + ParsedValue *output = NULL; if (!inline_flag) { switch (token->type) { @@ -40,6 +42,18 @@ ParsedValue *parse_token(char *file, DArray *tokens, }; } switch (token->type) { + case TOKEN_TRUE: + (*index)++; + output = parse_true(); + break; + case TOKEN_FALSE: + (*index)++; + output = parse_false(); + break; + case TOKEN_NULL: + (*index)++; + output = parse_null(); + break; case TOKEN_STRING: (*index)++; output = parse_string(*token); @@ -64,6 +78,9 @@ ParsedValue *parse_token(char *file, DArray *tokens, (*index)++; output = parse_number(token); break; + case TOKEN_LET: + output = parse_declaration(file, tokens, index); + break; default: fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line, token->column); @@ -85,8 +102,8 @@ ParsedValue *parse_token(char *file, DArray *tokens, case TOKEN_ASSIGN_STAR:; output = parse_assign(file, tokens, output, index); break; - default: - passed = true; + default: + passed = true; } } @@ -96,8 +113,7 @@ ParsedValue *parse_token(char *file, DArray *tokens, void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { size_t index = 0; while (index < tokens->size) { - ParsedValue *parsed_code = - parse_token(file, tokens, &index, inline_flag); + ParsedValue *parsed_code = parse_token(file, tokens, &index, inline_flag); if (parsed_code) { darray_push(parsed, parsed_code); free(parsed_code); @@ -116,6 +132,8 @@ void free_parsed(void *ptr) { free_parse_assign(parsed); break; case AST_NUMBER: + case AST_NULL: + case AST_BOOLEAN: break; case AST_IF: free_parsed_if(parsed); diff --git a/src/parser/parser.h b/src/parser/parser.h index 562a06e..242b0e0 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -15,7 +15,9 @@ typedef enum { AST_IF, AST_ACCESS, AST_CALL, - AST_DECLARATION + AST_DECLARATION, + AST_NULL, + AST_BOOLEAN } ValueType; extern const char* ValueTypeNames[]; diff --git a/test.ar b/test.ar index 1b7fa96..1813ee1 100644 --- a/test.ar +++ b/test.ar @@ -1,4 +1,2 @@ -let y = 0 -let x = 10 - -if (y) x += 1 \ No newline at end of file +let a +a = 10 \ No newline at end of file