add declaring and assignment with parser LHS support

This commit is contained in:
2025-06-04 21:20:44 +01:00
parent 9417cbe57a
commit 2bd0384060
17 changed files with 244 additions and 87 deletions

View File

@@ -3,8 +3,8 @@
{ {
"name": "Linux", "name": "Linux",
"compilerPath": "/usr/bin/clang", "compilerPath": "/usr/bin/clang",
"cStandard": "c99", "cStandard": "C23",
"cppStandard": "c++99", "cppStandard": "c++23",
"intelliSenseMode": "linux-clang-x64", "intelliSenseMode": "linux-clang-x64",
"includePath": [ "includePath": [
"${workspaceFolder}/**" "${workspaceFolder}/**"

View File

@@ -7,26 +7,26 @@
#define GET_STATE LexerState *state = (LexerState *)yyget_extra(yyscanner); #define GET_STATE LexerState *state = (LexerState *)yyget_extra(yyscanner);
#define COLUMN_NO state->current_column #define COLUMN_NO state->current_column
int yywrap(void *) { int yywrap(void * unused_param) {
(void)unused_param;
return 1; return 1;
} }
%} %}
%% %%
"." { return TOKEN_DOT; } "." { return TOKEN_DOT; }
"," {return TOKEN_COMMA; } "," { return TOKEN_COMMA; }
":" {return TOKEN_COLON; } ":" { return TOKEN_COLON; }
"=" { return TOKEN_ASSIGN; } "=" { return TOKEN_ASSIGN; }
"+=" { return TOKEN_ASSIGN_PLUS; } "+=" { return TOKEN_ASSIGN_PLUS; }
"-=" { return TOKEN_ASSIGN_MINUS; } "-=" { return TOKEN_ASSIGN_MINUS; }
"//=" { return TOKEN_ASSIGN_FLOORDIV; } "//=" { return TOKEN_ASSIGN_FLOORDIV; }
"/=" { return TOKEN_ASSIGN_SLASH; } "/=" { return TOKEN_ASSIGN_SLASH; }
"%=" { return TOKEN_ASSIGN_MODULO; } "%=" { return TOKEN_ASSIGN_MODULO; }
"*=" { return TOKEN_ASSIGN_STAR; } "*=" { return TOKEN_ASSIGN_STAR; }
"^=" { return TOKEN_ASSIGN_CARET; } "^=" { return TOKEN_ASSIGN_CARET; }
"not"[ \t]+"in" { return TOKEN_NOT_IN; } "not"[ \t]+"in" { return TOKEN_NOT_IN; }
"&&" { return TOKEN_AND; } "&&" { return TOKEN_AND; }
@@ -47,7 +47,7 @@ int yywrap(void *) {
"if" { return TOKEN_IF; } "if" { return TOKEN_IF; }
"else if" { return TOKEN_ELSE_IF; } "else"[ \t]+"if" { return TOKEN_ELSE_IF; }
"else" { return TOKEN_ELSE; } "else" { return TOKEN_ELSE; }
"while" { return TOKEN_WHILE; } "while" { return TOKEN_WHILE; }
"forever" { return TOKEN_FOREVER; } "forever" { return TOKEN_FOREVER; }

View File

@@ -0,0 +1,28 @@
#include "access.h"
#include "../../../lexer/token.h"
#include "../../parser.h"
#include <string.h>
#include <stdlib.h>
#include "../../../memory.h"
ParsedValue *parse_access(char*file,DArray *tokens, size_t * index, ParsedValue * to_access) {
(*index)++;
error_if_finished(file, tokens, index);
Token * token = darray_get(tokens, *index);
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess));
parsedAccess->to_access = to_access;
parsedAccess->access = strcpy(checked_malloc(sizeof(token->value)), token->value);
parsedValue->type = AST_ACCESS;
parsedValue->data = parsedAccess;
return parsedValue;
}
void free_parse_access(void *ptr) {
ParsedValue *parsedValue = ptr;
ParsedAccess *parsedAccess = parsedValue->data;
free_parsed(parsedAccess->to_access);
free(parsedAccess->access);
free(parsedAccess->to_access);
free(parsedAccess);
}

View File

@@ -0,0 +1,16 @@
#ifndef ACCESS_H
#define ACCESS_H
#include "../../parser.h"
#include "../../../lexer/token.h" // for Token
typedef struct {
ParsedValue * to_access;
char * access;
} ParsedAccess;
// Function declaration for parsing an identifier
ParsedValue *parse_access(char*file,DArray *tokens, size_t * index, ParsedValue * to_access);
void free_parse_access(void *ptr);
#endif // ACCESS_H

View File

@@ -1,21 +1,14 @@
#include "assign.h" #include "assign.h"
#include "../../lexer/token.h" #include "../../../lexer/token.h"
#include "../parser.h" #include "../../parser.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../../memory.h" #include "../../../memory.h"
ParsedValue *parse_assign(char *file, DArray *parsed, DArray *tokens, ParsedValue *parse_assign(char *file, DArray *tokens,
ParsedValue *assign_to, size_t *index) { ParsedValue *assign_to, size_t *index) {
bool islet = false;
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
if (token->type == TOKEN_LET) {
islet = true;
(*index)++;
error_if_finished(file,tokens,index);
token = darray_get(tokens, *index);
}
switch (assign_to->type) { switch (assign_to->type) {
case AST_IDENTIFIER: case AST_IDENTIFIER:
case AST_ASSIGN: case AST_ASSIGN:
@@ -31,8 +24,7 @@ ParsedValue *parse_assign(char *file, DArray *parsed, DArray *tokens,
(*index)++; (*index)++;
error_if_finished(file,tokens,index); error_if_finished(file,tokens,index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
assign->from = parse_token(file, parsed, tokens, index, true); assign->from = parse_token(file, tokens, index, true);
assign->let = islet;
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_ASSIGN; parsedValue->type = AST_ASSIGN;
parsedValue->data = assign; parsedValue->data = assign;

View File

@@ -1,16 +1,15 @@
#ifndef ASSIGN_H #ifndef ASSIGN_H
#define ASSIGN_H #define ASSIGN_H
#include "../parser.h" #include "../../parser.h"
#include "../../lexer/token.h" #include "../../../lexer/token.h"
typedef struct { typedef struct {
bool let;
ParsedValue * to; ParsedValue * to;
TokenType type; TokenType type;
ParsedValue * from; ParsedValue * from;
} ParsedAssign; } ParsedAssign;
ParsedValue *parse_assign(char*file,DArray *parsed, DArray *tokens, ParsedValue *parse_assign(char*file, DArray *tokens,
ParsedValue *assign_to, size_t *index); ParsedValue *assign_to, size_t *index);
void free_parse_assign(void*ptr); void free_parse_assign(void*ptr);

View File

@@ -0,0 +1,59 @@
#include "call.h"
#include "../../../lexer/token.h"
#include "../../../memory.h"
#include "../../parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ParsedValue *parse_call(char *file, DArray *tokens, size_t *index,
ParsedValue *to_call) {
(*index)++;
error_if_finished(file, tokens, index);
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
ParsedCall *parsedCall = checked_malloc(sizeof(ParsedCall));
DArray *args = checked_malloc(sizeof(DArray));
darray_init(args, sizeof(ParsedValue));
parsedCall->to_call = to_call;
parsedCall->args = args;
parsedValue->type = AST_ACCESS;
parsedValue->data = parsedCall;
Token *token = darray_get(tokens, *index);
DArray *arg = checked_malloc(sizeof(DArray));
darray_init(arg, sizeof(ParsedValue));
while (true) {
bool to_break = false;
switch (token->type) {
case TOKEN_RPAREN:
to_break = true;
break;
default:
break;
}
if (to_break)
break;
ParsedValue *parsedValue = parse_token(file, tokens, index, true);
darray_push(arg, parsedValue);
switch (token->type) {
case TOKEN_COMMA:
darray_push(args, arg);
arg = checked_malloc(sizeof(DArray));
darray_init(arg, sizeof(ParsedValue));
break;
default:
break;
}
}
return parsedValue;
}
void free_parse_call(void *ptr) {
ParsedValue *parsedValue = ptr;
ParsedCall *parsedCall = parsedValue->data;
free_parsed(parsedCall->to_call);
free(parsedCall);
}

View File

@@ -0,0 +1,16 @@
#ifndef CALL_H
#define CALL_H
#include "../../parser.h"
#include "../../../lexer/token.h" // for Token
typedef struct {
ParsedValue * to_call;
DArray * args;
} ParsedCall;
// Function declaration for parsing an identifier
ParsedValue *parse_call(char *file, DArray *tokens, size_t *index,
ParsedValue *to_call);
void free_parse_call(void *ptr);
#endif // CALL_H

View File

@@ -1,8 +1,8 @@
#include "identifier.h" #include "identifier.h"
#include "../../lexer/token.h" #include "../../../lexer/token.h"
#include "../parser.h" #include "../../parser.h"
#include <string.h> #include <string.h>
#include "../../memory.h" #include "../../../memory.h"
ParsedValue *parse_identifier(Token *token) { ParsedValue *parse_identifier(Token *token) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));

View File

@@ -2,8 +2,8 @@
#ifndef IDENTIFIER_H #ifndef IDENTIFIER_H
#define IDENTIFIER_H #define IDENTIFIER_H
#include "../parser.h" #include "../../parser.h"
#include "../../lexer/token.h" // for Token #include "../../../lexer/token.h" // for Token
// Function declaration for parsing an identifier // Function declaration for parsing an identifier
ParsedValue * parse_identifier(Token * token); ParsedValue * parse_identifier(Token * token);

View File

@@ -0,0 +1,30 @@
#include "declaration.h"
#include "../../lexer/token.h"
#include "../../memory.h"
#include "../parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens,
size_t *index) {
(*index)++;
error_if_finished(file, tokens, index);
Token *token = darray_get(tokens, *index);
ParsedValue * parsedValue = malloc(sizeof(ParsedValue));
ParsedDeclaration * declaration = malloc(sizeof(ParsedDeclaration));
parsedValue->data = declaration;
parsedValue->type = AST_DECLARATION;
if (token->type != TOKEN_IDENTIFIER) {
fprintf(stderr, "%s:%u:%u error: declaration requires an identifier\n",
file, token->line, token->column);
exit(EXIT_FAILURE);
}
declaration->name = strcpy(checked_malloc(sizeof(token->value)), token->value);
(*index)++;
if ((*index) >= tokens->size) return parsedValue;
token = darray_get(tokens, *index);
return parsedValue;
}

View File

@@ -0,0 +1,16 @@
#ifndef DECLARATION_H
#define DECLARATION_H
#include "../parser.h"
#include "../../lexer/token.h" // for Token
typedef struct {
char * name;
bool is_function;
DArray args; // string[]
ParsedValue * from;
} ParsedDeclaration;
// Function declaration for parsing an identifier
ParsedValue *parse_declaration(char *file, DArray *parsed, DArray *tokens, size_t *index);
#endif // DECLARATION_H

View File

@@ -6,7 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "../../memory.h" #include "../../memory.h"
ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens, ParsedValue *parse_if(char *file, DArray *tokens,
size_t *index) { size_t *index) {
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
@@ -54,7 +54,7 @@ ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens,
darray_init(condition, sizeof(ParsedValue)); darray_init(condition, sizeof(ParsedValue));
while (*index < tokens->size) { while (*index < tokens->size) {
ParsedValue *parsed_code = parse_token(file, parsed, tokens, index, true); ParsedValue *parsed_code = parse_token(file, tokens, index, true);
if (parsed_code) { if (parsed_code) {
darray_push(condition, parsed_code); darray_push(condition, parsed_code);
free(parsed_code); free(parsed_code);
@@ -78,7 +78,7 @@ ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens,
// Parse the body // Parse the body
ParsedValue *parsed_content = ParsedValue *parsed_content =
parse_token(file, parsed, tokens, index, false); parse_token(file, tokens, index, false);
if (!parsed_content) { if (!parsed_content) {
fprintf(stderr, fprintf(stderr,
@@ -120,6 +120,7 @@ void free_conditional(void *ptr) {
if (conditional->condition) if (conditional->condition)
darray_free(conditional->condition, free_parsed); darray_free(conditional->condition, free_parsed);
free_parsed(conditional->content); free_parsed(conditional->content);
free(conditional->content);
} }
void free_parsed_if(void *ptr) { void free_parsed_if(void *ptr) {

View File

@@ -10,7 +10,7 @@ typedef struct {
ParsedValue *content; ParsedValue *content;
} ParsedConditional; } ParsedConditional;
ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens, ParsedValue *parse_if(char *file, DArray *tokens,
size_t *index); size_t *index);
void free_parsed_if(void *ptr); void free_parsed_if(void *ptr);

View File

@@ -1,8 +1,8 @@
#include "parser.h" #include "parser.h"
#include "../dynamic_array/darray.h" #include "../dynamic_array/darray.h"
#include "../lexer/token.h" #include "../lexer/token.h"
#include "assign/assign.h" #include "assignable/assign/assign.h"
#include "identifier/identifier.h" #include "assignable/identifier/identifier.h"
#include "if/if.h" #include "if/if.h"
#include "number/number.h" #include "number/number.h"
#include "string/string.h" #include "string/string.h"
@@ -12,8 +12,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
const char *ValueTypeNames[] = {"string", "assign", "identifier", "number", const char *ValueTypeNames[] = {"string", "assign", "identifier",
"if statement"}; "number", "if statement", "access",
"call"};
void error_if_finished(char *file, DArray *tokens, size_t *index) { void error_if_finished(char *file, DArray *tokens, size_t *index) {
if ((*index) >= tokens->size) { if ((*index) >= tokens->size) {
@@ -24,13 +25,16 @@ void error_if_finished(char *file, DArray *tokens, size_t *index) {
} }
} }
ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, ParsedValue *parse_token(char *file, DArray *tokens,
size_t *index, bool inline_flag) { size_t *index, bool inline_flag) {
Token *token = darray_get(tokens, *index); Token *token = darray_get(tokens, *index);
ParsedValue * output = NULL;
if (!inline_flag) { if (!inline_flag) {
switch (token->type) { switch (token->type) {
case TOKEN_IF: case TOKEN_IF:
return parse_if(file, parsed, tokens, index); return parse_if(file, tokens, index);
default: default:
break; break;
}; };
@@ -38,24 +42,37 @@ ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens,
switch (token->type) { switch (token->type) {
case TOKEN_STRING: case TOKEN_STRING:
(*index)++; (*index)++;
return parse_string(*token); output = parse_string(*token);
break;
case TOKEN_NEW_LINE: case TOKEN_NEW_LINE:
while (token->type == TOKEN_NEW_LINE && ++(*index) < tokens->size) { while (token->type == TOKEN_NEW_LINE && ++(*index) < tokens->size) {
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
} }
if (token->type == TOKEN_NEW_LINE) if (token->type == TOKEN_NEW_LINE)
return NULL; break;
return parse_token(file, parsed, tokens, index, inline_flag); output = parse_token(file, tokens, index, inline_flag);
break;
case TOKEN_INDENT: case TOKEN_INDENT:
fprintf(stderr, "%s:%u:%u error: invalid indentation\n", file, token->line, fprintf(stderr, "%s:%u:%u error: invalid indentation\n", file, token->line,
token->column); token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case TOKEN_LET: case TOKEN_IDENTIFIER:
case TOKEN_IDENTIFIER:;
ParsedValue *assign_to = parse_identifier(token);
(*index)++; (*index)++;
if (*index >= tokens->size) output = parse_identifier(token);
return assign_to; break;
case TOKEN_NUMBER:
(*index)++;
output = parse_number(token);
break;
default:
fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line,
token->column);
exit(EXIT_FAILURE);
}
// LHS required
bool passed = false;
while (!passed && (*index) < tokens->size) {
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
switch (token->type) { switch (token->type) {
case TOKEN_ASSIGN: case TOKEN_ASSIGN:
@@ -66,43 +83,21 @@ ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens,
case TOKEN_ASSIGN_PLUS: case TOKEN_ASSIGN_PLUS:
case TOKEN_ASSIGN_SLASH: case TOKEN_ASSIGN_SLASH:
case TOKEN_ASSIGN_STAR:; case TOKEN_ASSIGN_STAR:;
DArray slice = darray_slice(parsed, parsed->size, parsed->size); output = parse_assign(file, tokens, output, index);
return parse_assign(file, &slice, tokens, assign_to, index); break;
default: default:
return assign_to; passed = true;
} }
case TOKEN_ASSIGN:
case TOKEN_ASSIGN_CARET:
case TOKEN_ASSIGN_FLOORDIV:
case TOKEN_ASSIGN_MINUS:
case TOKEN_ASSIGN_MODULO:
case TOKEN_ASSIGN_PLUS:
case TOKEN_ASSIGN_SLASH:
case TOKEN_ASSIGN_STAR:
if (parsed->size == 0) {
fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line,
token->column);
exit(EXIT_FAILURE);
}
ParsedValue *assigning_to = darray_get(parsed, parsed->size - 1);
fprintf(stderr, "%s:%u:%u error: cannot assign to %s\n", file, token->line,
token->column, ValueTypeNames[assigning_to->type]);
exit(EXIT_FAILURE);
case TOKEN_NUMBER:
(*index)++;
return parse_number(token);
default:
fprintf(stderr, "%s:%u:%u error: syntax error\n", file, token->line,
token->column);
exit(EXIT_FAILURE);
} }
return output;
} }
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) {
size_t index = 0; size_t index = 0;
while (index < tokens->size) { while (index < tokens->size) {
ParsedValue *parsed_code = ParsedValue *parsed_code =
parse_token(file, parsed, tokens, &index, inline_flag); parse_token(file, tokens, &index, inline_flag);
if (parsed_code) { if (parsed_code) {
darray_push(parsed, parsed_code); darray_push(parsed, parsed_code);
free(parsed_code); free(parsed_code);

View File

@@ -13,6 +13,9 @@ typedef enum {
AST_IDENTIFIER, AST_IDENTIFIER,
AST_NUMBER, AST_NUMBER,
AST_IF, AST_IF,
AST_ACCESS,
AST_CALL,
AST_DECLARATION
} ValueType; } ValueType;
extern const char* ValueTypeNames[]; extern const char* ValueTypeNames[];
@@ -24,7 +27,7 @@ typedef struct {
void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag); void parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag);
ParsedValue *parse_token(char *file, DArray *parsed, DArray *tokens, ParsedValue *parse_token(char *file, DArray *tokens,
size_t *index, bool inline_flag); size_t *index, bool inline_flag);
void free_parsed(void *ptr); void free_parsed(void *ptr);

View File

@@ -1,2 +1,4 @@
let x = 10 # hello world let y = 0
if (x = 10) "hello world" let x = 10
if (y) x += 1