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",
"compilerPath": "/usr/bin/clang",
"cStandard": "c99",
"cppStandard": "c++99",
"cStandard": "C23",
"cppStandard": "c++23",
"intelliSenseMode": "linux-clang-x64",
"includePath": [
"${workspaceFolder}/**"

View File

@@ -7,26 +7,26 @@
#define GET_STATE LexerState *state = (LexerState *)yyget_extra(yyscanner);
#define COLUMN_NO state->current_column
int yywrap(void *) {
int yywrap(void * unused_param) {
(void)unused_param;
return 1;
}
%}
%%
"." { return TOKEN_DOT; }
"," {return TOKEN_COMMA; }
":" {return TOKEN_COLON; }
"." { return TOKEN_DOT; }
"," { return TOKEN_COMMA; }
":" { return TOKEN_COLON; }
"=" { return TOKEN_ASSIGN; }
"+=" { return TOKEN_ASSIGN_PLUS; }
"-=" { return TOKEN_ASSIGN_MINUS; }
"//=" { return TOKEN_ASSIGN_FLOORDIV; }
"/=" { return TOKEN_ASSIGN_SLASH; }
"%=" { return TOKEN_ASSIGN_MODULO; }
"*=" { return TOKEN_ASSIGN_STAR; }
"^=" { return TOKEN_ASSIGN_CARET; }
"+=" { return TOKEN_ASSIGN_PLUS; }
"-=" { return TOKEN_ASSIGN_MINUS; }
"//=" { return TOKEN_ASSIGN_FLOORDIV; }
"/=" { return TOKEN_ASSIGN_SLASH; }
"%=" { return TOKEN_ASSIGN_MODULO; }
"*=" { return TOKEN_ASSIGN_STAR; }
"^=" { return TOKEN_ASSIGN_CARET; }
"not"[ \t]+"in" { return TOKEN_NOT_IN; }
"&&" { return TOKEN_AND; }
@@ -47,7 +47,7 @@ int yywrap(void *) {
"if" { return TOKEN_IF; }
"else if" { return TOKEN_ELSE_IF; }
"else"[ \t]+"if" { return TOKEN_ELSE_IF; }
"else" { return TOKEN_ELSE; }
"while" { return TOKEN_WHILE; }
"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 "../../lexer/token.h"
#include "../parser.h"
#include "../../../lexer/token.h"
#include "../../parser.h"
#include <stdbool.h>
#include <stdio.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) {
bool islet = false;
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) {
case AST_IDENTIFIER:
case AST_ASSIGN:
@@ -31,8 +24,7 @@ ParsedValue *parse_assign(char *file, DArray *parsed, DArray *tokens,
(*index)++;
error_if_finished(file,tokens,index);
token = darray_get(tokens, *index);
assign->from = parse_token(file, parsed, tokens, index, true);
assign->let = islet;
assign->from = parse_token(file, tokens, index, true);
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type = AST_ASSIGN;
parsedValue->data = assign;

View File

@@ -1,16 +1,15 @@
#ifndef ASSIGN_H
#define ASSIGN_H
#include "../parser.h"
#include "../../lexer/token.h"
#include "../../parser.h"
#include "../../../lexer/token.h"
typedef struct {
bool let;
ParsedValue * to;
TokenType type;
ParsedValue * from;
} ParsedAssign;
ParsedValue *parse_assign(char*file,DArray *parsed, DArray *tokens,
ParsedValue *parse_assign(char*file, DArray *tokens,
ParsedValue *assign_to, size_t *index);
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 "../../lexer/token.h"
#include "../parser.h"
#include "../../../lexer/token.h"
#include "../../parser.h"
#include <string.h>
#include "../../memory.h"
#include "../../../memory.h"
ParsedValue *parse_identifier(Token *token) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));

View File

@@ -2,8 +2,8 @@
#ifndef IDENTIFIER_H
#define IDENTIFIER_H
#include "../parser.h"
#include "../../lexer/token.h" // for Token
#include "../../parser.h"
#include "../../../lexer/token.h" // for Token
// Function declaration for parsing an identifier
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 "../../memory.h"
ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens,
ParsedValue *parse_if(char *file, DArray *tokens,
size_t *index) {
(*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));
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) {
darray_push(condition, parsed_code);
free(parsed_code);
@@ -78,7 +78,7 @@ ParsedValue *parse_if(char *file, DArray *parsed, DArray *tokens,
// Parse the body
ParsedValue *parsed_content =
parse_token(file, parsed, tokens, index, false);
parse_token(file, tokens, index, false);
if (!parsed_content) {
fprintf(stderr,
@@ -120,6 +120,7 @@ void free_conditional(void *ptr) {
if (conditional->condition)
darray_free(conditional->condition, free_parsed);
free_parsed(conditional->content);
free(conditional->content);
}
void free_parsed_if(void *ptr) {

View File

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

View File

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

View File

@@ -13,6 +13,9 @@ typedef enum {
AST_IDENTIFIER,
AST_NUMBER,
AST_IF,
AST_ACCESS,
AST_CALL,
AST_DECLARATION
} ValueType;
extern const char* ValueTypeNames[];
@@ -24,7 +27,7 @@ typedef struct {
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);
void free_parsed(void *ptr);

View File

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