summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-30 04:50:11 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-30 04:50:11 +0330
commite6122f465cd8b8eebcc2657321cf7cf5732408a8 (patch)
tree127d56cab08e99b0999c909db98a417656bf001f /src/compiler
parent6441d6ace4b3ebdc04e3e7fee212830f783eecb0 (diff)
added global variables (not constants)
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/ast-tree.c117
-rw-r--r--src/compiler/ast-tree.h7
-rw-r--r--src/compiler/code-generator.c64
-rw-r--r--src/compiler/code-generator.h3
-rw-r--r--src/compiler/lexer.c5
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c22
-rw-r--r--src/compiler/parser.h1
8 files changed, 192 insertions, 28 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 87f4755..8043561 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -23,6 +23,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_FUNCTION_CALL",
"AST_TREE_TOKEN_VARIABLE",
+ "AST_TREE_TOKEN_VARIABLE_DEFINE",
"AST_TREE_TOKEN_VALUE_U64",
"AST_TREE_TOKEN_NONE",
@@ -73,6 +74,7 @@ void astTreePrint(const AstTree *tree, int indent) {
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
goto RETURN_SUCCESS;
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = tree->metadata;
@@ -175,6 +177,7 @@ void astTreeDestroy(AstTree tree) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return;
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = tree.metadata;
@@ -262,6 +265,7 @@ AstTree *copyAstTree(AstTree *tree) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_NONE:
}
printLog("Bad token '%d'", tree->token);
@@ -288,7 +292,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
goto RETURN_ERROR;
}
ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
- if (node->token != PARSER_TOKEN_CONSTANT) {
+ if (node->token != PARSER_TOKEN_CONSTANT &&
+ node->token != PARSER_TOKEN_VARIABLE) {
printLog("Unexpected %s", PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
}
@@ -297,6 +302,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
AstTreeVariable *variable = a404m_malloc(sizeof(*variable));
variable->name_begin = node_metadata->name->str_begin;
variable->name_end = node_metadata->name->str_end;
+ variable->isConst = node->token == PARSER_TOKEN_CONSTANT;
if (!pushVariable(&root->variables, variable)) {
astTreeVariableDelete(variable);
@@ -312,7 +318,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
(ParserNodeSingleChildMetadata *)nodes->data[i]->metadata;
ParserNodeVariableMetadata *node_metadata = node->metadata;
- if (node->token != PARSER_TOKEN_CONSTANT) {
+ if (node->token != PARSER_TOKEN_CONSTANT &&
+ node->token != PARSER_TOKEN_VARIABLE) {
printLog("Only variables are allowed here");
goto RETURN_ERROR;
}
@@ -334,6 +341,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_TYPE_U64:
case PARSER_TOKEN_KEYWORD_PRINT_U64:
case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -452,6 +460,7 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
(void *)(AstTreeU64)(ParserNodeU64Metadata)parserNode->metadata);
case PARSER_TOKEN_KEYWORD_PRINT_U64:
return astTreeParsePrintU64(parserNode, variables, variables_size);
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -516,6 +525,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
argument->type = type;
argument->name_begin = arg_metadata->name->str_begin;
argument->name_end = arg_metadata->name->str_end;
+ argument->isConst = false; // all arguments are not constants
if (!pushVariable(&function->arguments, argument)) {
astTreeVariableDelete(argument);
@@ -536,8 +546,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
goto RETURN_ERROR;
}
} else {
- AstTree *tree;
- tree = astTreeParse(node, variables, variables_size);
+ AstTree *tree = astTreeParse(node, variables, variables_size);
if (tree == NULL) {
goto RETURN_ERROR;
@@ -716,6 +725,7 @@ bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
variable->value = value;
variable->name_begin = node_metadata->name->str_begin;
variable->name_end = node_metadata->name->str_end;
+ variable->isConst = true;
if (!pushVariable(variables[variables_size - 1], variable)) {
astTreeVariableDelete(variable);
@@ -727,6 +737,50 @@ RETURN_ERROR:
return false;
}
+AstTree *astTreeParseVariable(ParserNode *parserNode,
+ AstTreeVariables **variables,
+ size_t variables_size) {
+ ParserNodeVariableMetadata *node_metadata = parserNode->metadata;
+
+ if (node_metadata->value == NULL ||
+ node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) {
+ printLog("Not supported");
+ return NULL;
+ }
+
+ AstTree *value =
+ astTreeParse(node_metadata->value, variables, variables_size);
+ if (value == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ AstTree *type;
+ if (node_metadata->type == NULL) {
+ type = NULL;
+ } else {
+ type = astTreeParse(node_metadata->type, variables, variables_size);
+ if (type == NULL) {
+ goto RETURN_ERROR;
+ }
+ }
+
+ AstTreeVariable *variable = a404m_malloc(sizeof(*variable));
+ variable->type = type;
+ variable->value = value;
+ variable->name_begin = node_metadata->name->str_begin;
+ variable->name_end = node_metadata->name->str_end;
+ variable->isConst = false;
+
+ if (!pushVariable(variables[variables_size - 1], variable)) {
+ astTreeVariableDelete(variable);
+ goto RETURN_ERROR;
+ }
+
+ return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable);
+RETURN_ERROR:
+ return NULL;
+}
+
bool hasTypeOf(AstTree *value, const AstTree *type) {
if (value->token == AST_TREE_TOKEN_VARIABLE) {
AstTreeVariable *variable = value->metadata;
@@ -746,8 +800,9 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_VALUE_U64:
- case AST_TREE_TOKEN_NONE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
+ case AST_TREE_TOKEN_NONE:
}
goto ERROR;
case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -774,6 +829,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -786,6 +842,7 @@ bool hasTypeOf(AstTree *value, const AstTree *type) {
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -813,6 +870,7 @@ bool isFunction(AstTree *value) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -820,6 +878,29 @@ bool isFunction(AstTree *value) {
exit(1);
}
+bool isConst(AstTree *value) {
+ switch (value->token) {
+ case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_VALUE_U64:
+ return true;
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ return false;
+ case AST_TREE_TOKEN_VARIABLE: {
+ AstTreeVariable *metadata = value->metadata;
+ return metadata->isConst;
+ }
+ case AST_TREE_TOKEN_NONE:
+ }
+ printLog("Bad token '%d'", value->token);
+ exit(1);
+}
+
AstTree *makeTypeOf(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_TYPE_TYPE:
@@ -854,6 +935,7 @@ AstTree *makeTypeOf(AstTree *value) {
AstTreeVariable *variable = value->metadata;
return copyAstTree(variable->type);
}
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_NONE:
}
@@ -866,6 +948,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -911,6 +994,7 @@ bool setAllTypes(AstTree *tree) {
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return true;
case AST_TREE_TOKEN_FUNCTION:
return setTypesFunction(tree);
@@ -1052,6 +1136,7 @@ bool astTreeClean(AstTree *tree) {
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
return true;
case AST_TREE_TOKEN_NONE:
}
@@ -1096,16 +1181,24 @@ bool astTreeCleanAstVariable(AstTreeVariable *variable) {
return false;
}
AstTree *value = variable->value;
- if (value->token == AST_TREE_TOKEN_VARIABLE) {
- do {
- AstTreeVariable *value_metadata = value->metadata;
- AstTree *newValue = value_metadata->value;
- astTreeDelete(value);
- value = newValue;
- } while (value->token == AST_TREE_TOKEN_VARIABLE);
+ while (value->token == AST_TREE_TOKEN_VARIABLE) {
+ AstTreeVariable *value_metadata = value->metadata;
+ if (!value_metadata->isConst) {
+ break;
+ }
+ AstTree *newValue = value_metadata->value;
+ astTreeDelete(value);
+ value = newValue;
+ }
+
+ if (variable->value != value) {
variable->value = copyAstTree(value);
}
+ if (variable->isConst && !isConst(value)) {
+ return false;
+ }
+
return true;
}
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index b9c1585..90133a5 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -16,6 +16,7 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_FUNCTION_CALL,
AST_TREE_TOKEN_VARIABLE,
+ AST_TREE_TOKEN_VARIABLE_DEFINE,
AST_TREE_TOKEN_VALUE_U64,
AST_TREE_TOKEN_NONE,
@@ -32,6 +33,7 @@ typedef struct AstTreeVariable {
char *name_end;
AstTree *type;
AstTree *value;
+ bool isConst;
} AstTreeVariable;
typedef struct AstTreeVariables {
@@ -118,8 +120,13 @@ AstTree *astTreeParsePrintU64(ParserNode *parserNode,
bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
size_t variables_size);
+AstTree *astTreeParseVariable(ParserNode *parserNode,
+ AstTreeVariables **variables,
+ size_t variables_size);
+
bool hasTypeOf(AstTree *value, const AstTree *type);
bool isFunction(AstTree *value);
+bool isConst(AstTree *value);
AstTree *makeTypeOf(AstTree *value);
bool typeIsEqual(const AstTree *type0, const AstTree *type1);
diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c
index 4c0becb..b084995 100644
--- a/src/compiler/code-generator.c
+++ b/src/compiler/code-generator.c
@@ -2,6 +2,7 @@
#include "compiler/ast-tree.h"
#include "utils/log.h"
#include "utils/memory.h"
+#include "utils/string.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
@@ -13,6 +14,10 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) {
CodeGeneratorCode current = code->codes[i];
switch (current.instruction) {
case CODE_GENERATOR_INSTRUCTION_PRINT_U64:
+ case CODE_GENERATOR_INSTRUCTION_DEF_VAR64: {
+ CodeGeneratorOperand *metadata = current.metadata;
+ free(metadata);
+ }
case CODE_GENERATOR_INSTRUCTION_RET:
continue;
case CODE_GENERATOR_INSTRUCTION_CALL: {
@@ -78,6 +83,14 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) {
}
continue;
case AST_TREE_TOKEN_VALUE_U64:
+ if (!variable->isConst) {
+ CodeGeneratorOperand value =
+ u64ToString((AstTreeU64)variable->value->metadata);
+ generateCodePushCode(
+ codes,
+ createGenerateCode(variable->name_begin, variable->name_end,
+ CODE_GENERATOR_INSTRUCTION_DEF_VAR64, value));
+ }
continue;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -86,6 +99,7 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_NONE:
break;
}
@@ -128,24 +142,39 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = tree.metadata;
if (metadata->token == AST_TREE_TOKEN_VALUE_U64) {
- CodeGeneratorOperandU64 value = (AstTreeU64)metadata->metadata;
+ CodeGeneratorOperand value =
+ u64ToString((AstTreeU64)metadata->metadata);
generateCodePushCode(
- codes, createGenerateCode(label_begin, label_end,
- CODE_GENERATOR_INSTRUCTION_PRINT_U64,
- (void *)value));
+ codes,
+ createGenerateCode(label_begin, label_end,
+ CODE_GENERATOR_INSTRUCTION_PRINT_U64, value));
} else if (metadata->token == AST_TREE_TOKEN_VARIABLE) {
AstTreeVariable *variable = metadata->metadata;
- CodeGeneratorOperandU64 value = (AstTreeU64)variable->value->metadata;
- generateCodePushCode(
- codes, createGenerateCode(label_begin, label_end,
- CODE_GENERATOR_INSTRUCTION_PRINT_U64,
- (void *)value));
+ if (variable->isConst) {
+ CodeGeneratorOperand value =
+ u64ToString((AstTreeU64)variable->value->metadata);
+ generateCodePushCode(
+ codes, createGenerateCode(label_begin, label_end,
+ CODE_GENERATOR_INSTRUCTION_PRINT_U64,
+ (void *)value));
+ } else {
+ char *name = a404m_malloc(
+ (variable->name_end - variable->name_begin + 1) * sizeof(*name));
+ strncpy(name, variable->name_begin,
+ variable->name_end - variable->name_begin);
+ name[variable->name_end - variable->name_begin] = '\0';
+ generateCodePushCode(
+ codes,
+ createGenerateCode(label_begin, label_end,
+ CODE_GENERATOR_INSTRUCTION_PRINT_U64, name));
+ }
} else {
printLog("Not implemented yet");
exit(1);
}
}
goto OK;
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_VALUE_U64:
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_FUNCTION:
@@ -207,9 +236,13 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) {
switch (code.instruction) {
case CODE_GENERATOR_INSTRUCTION_PRINT_U64: {
- CodeGeneratorOperandU64 metadata = (CodeGeneratorOperandU64)code.metadata;
+ CodeGeneratorOperand metadata = (CodeGeneratorOperand)code.metadata;
char *inst;
- asprintf(&inst, "mov rdi,%lu\ncall print_u64\n", (uint64_t)metadata);
+ if ('0' <= metadata[0] && metadata[0] <= '9') {
+ asprintf(&inst, "mov rdi,%s\ncall print_u64\n", metadata);
+ } else {
+ asprintf(&inst, "mov rdi,[%s]\ncall print_u64\n", metadata);
+ }
codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst,
strlen(inst));
free(inst);
@@ -233,6 +266,15 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) {
strlen(INST));
}
continue;
+ case CODE_GENERATOR_INSTRUCTION_DEF_VAR64: {
+ CodeGeneratorOperand metadata = (CodeGeneratorOperand)code.metadata;
+ char *inst;
+ asprintf(&inst, "db %s\n", metadata);
+ codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, inst,
+ strlen(inst));
+ free(inst);
+ }
+ continue;
}
printLog("Bad instruction %d", code.instruction);
}
diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h
index 03415a4..05a6bf4 100644
--- a/src/compiler/code-generator.h
+++ b/src/compiler/code-generator.h
@@ -8,6 +8,7 @@ typedef enum CodeGeneratorInstruction : uint8_t {
CODE_GENERATOR_INSTRUCTION_PRINT_U64,
CODE_GENERATOR_INSTRUCTION_CALL,
CODE_GENERATOR_INSTRUCTION_RET,
+ CODE_GENERATOR_INSTRUCTION_DEF_VAR64,
} CodeGeneratorInstruction;
typedef struct CodeGeneratorCode {
@@ -22,7 +23,7 @@ typedef struct CodeGeneratorCall {
char *label_end;
} CodeGeneratorCall;
-typedef uint64_t CodeGeneratorOperandU64;
+typedef char *CodeGeneratorOperand;
typedef struct CodeGeneratorCodes {
CodeGeneratorCode *codes;
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 464ec7e..071a2f8 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -26,13 +26,14 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET",
"LEXER_TOKEN_SYMBOL_FUNCTION_ARROW",
"LEXER_TOKEN_SYMBOL_COLON",
+ "LEXER_TOKEN_SYMBOL_ASSIGN",
"LEXER_TOKEN_SYMBOL_COMMA",
"LEXER_TOKEN_NONE",
};
const char *LEXER_SYMBOL_STRINGS[] = {
- ";", "(", ")", "{", "}", "->", ":", ",",
+ ";", "(", ")", "{", "}", "->", ":", "=", ",",
};
const LexerToken LEXER_SYMBOL_TOKENS[] = {
LEXER_TOKEN_SYMBOL_EOL,
@@ -42,6 +43,7 @@ const LexerToken LEXER_SYMBOL_TOKENS[] = {
LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET,
LEXER_TOKEN_SYMBOL_FUNCTION_ARROW,
LEXER_TOKEN_SYMBOL_COLON,
+ LEXER_TOKEN_SYMBOL_ASSIGN,
LEXER_TOKEN_SYMBOL_COMMA,
};
const size_t LEXER_SYMBOL_SIZE =
@@ -186,6 +188,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET:
case LEXER_TOKEN_SYMBOL_FUNCTION_ARROW:
case LEXER_TOKEN_SYMBOL_COLON:
+ case LEXER_TOKEN_SYMBOL_ASSIGN:
case LEXER_TOKEN_SYMBOL_COMMA:
if (*array_size == array->size) {
*array_size += 1 + *array_size / 2;
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 6efeac8..41c1ab7 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -20,6 +20,7 @@ typedef enum LexerToken {
LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET,
LEXER_TOKEN_SYMBOL_FUNCTION_ARROW,
LEXER_TOKEN_SYMBOL_COLON,
+ LEXER_TOKEN_SYMBOL_ASSIGN,
LEXER_TOKEN_SYMBOL_COMMA,
LEXER_TOKEN_NONE,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index 504e40a..2bdac64 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -23,6 +23,7 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_KEYWORD_PRINT_U64",
"PARSER_TOKEN_CONSTANT",
+ "PARSER_TOKEN_VARIABLE",
"PARSER_TOKEN_SYMBOL_EOL",
"PARSER_TOKEN_SYMBOL_CURLY_BRACKET",
@@ -105,7 +106,8 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(",operand=%lu", metadata);
}
goto RETURN_SUCCESS;
- case PARSER_TOKEN_CONSTANT: {
+ case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE: {
const ParserNodeVariableMetadata *metadata = node->metadata;
printf(",\n");
for (int i = 0; i < indent; ++i)
@@ -231,7 +233,8 @@ void parserNodeDelete(ParserNode *node) {
case PARSER_TOKEN_TYPE_U64:
case PARSER_TOKEN_VALUE_U64:
goto RETURN_SUCCESS;
- case PARSER_TOKEN_CONSTANT: {
+ case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE: {
ParserNodeVariableMetadata *metadata = node->metadata;
parserNodeDelete(metadata->name);
parserNodeDelete(metadata->type);
@@ -404,6 +407,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
case LEXER_TOKEN_SYMBOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET:
+ case LEXER_TOKEN_SYMBOL_ASSIGN:
}
printLog("Bad token '%d'", node->token);
return NULL;
@@ -688,7 +692,6 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *parent) {
ParserNode *variableNode = a404m_malloc(sizeof(*variableNode));
- variableNode->token = PARSER_TOKEN_CONSTANT;
variableNode->parent = parent;
LexerNode *nameNode = node - 1;
@@ -712,12 +715,18 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *type;
ParserNode *value;
+ ParserToken token = PARSER_TOKEN_VARIABLE;
+
if (node1 >= end) {
printLog("Bad variable definition");
return NULL;
} else if (node1->token == LEXER_TOKEN_SYMBOL_COLON) {
type = NULL;
node1->parserNode = variableNode;
+ token = PARSER_TOKEN_CONSTANT;
+ } else if (node1->token == LEXER_TOKEN_SYMBOL_ASSIGN) {
+ type = NULL;
+ node1->parserNode = variableNode;
} else if (node1->parserNode == NULL) {
printLog("Bad variable type with token '%s' %d",
LEXER_TOKEN_STRINGS[node1->token], node1->token);
@@ -735,6 +744,9 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
}
if (node1 < end && node1->token == LEXER_TOKEN_SYMBOL_COLON) {
node1->parserNode = variableNode;
+ token = PARSER_TOKEN_CONSTANT;
+ } else if (node1 < end && node1->token == LEXER_TOKEN_SYMBOL_COLON) {
+ node1->parserNode = variableNode;
} else {
node1 = NULL;
value = NULL;
@@ -770,6 +782,7 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
variableNode->str_end = type->str_end;
}
+ variableNode->token = token;
return node->parserNode = variableNode;
RETURN_ERROR:
@@ -791,6 +804,7 @@ bool isExpression(ParserNode *node) {
switch (node->token) {
case PARSER_TOKEN_IDENTIFIER:
case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_FUNCTION_CALL:
@@ -821,6 +835,7 @@ bool isType(ParserNode *node) {
return true;
case PARSER_TOKEN_IDENTIFIER:
case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_ROOT:
@@ -849,6 +864,7 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_TYPE_U64:
case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_SYMBOL_EOL:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 71aa9d8..c20fc12 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -19,6 +19,7 @@ typedef enum ParserToken {
PARSER_TOKEN_KEYWORD_PRINT_U64,
PARSER_TOKEN_CONSTANT,
+ PARSER_TOKEN_VARIABLE,
PARSER_TOKEN_SYMBOL_EOL,
PARSER_TOKEN_SYMBOL_CURLY_BRACKET,