diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/ast-tree.c | 117 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 7 | ||||
-rw-r--r-- | src/compiler/code-generator.c | 64 | ||||
-rw-r--r-- | src/compiler/code-generator.h | 3 | ||||
-rw-r--r-- | src/compiler/lexer.c | 5 | ||||
-rw-r--r-- | src/compiler/lexer.h | 1 | ||||
-rw-r--r-- | src/compiler/parser.c | 22 | ||||
-rw-r--r-- | src/compiler/parser.h | 1 | ||||
-rw-r--r-- | src/utils/string.c | 21 | ||||
-rw-r--r-- | src/utils/string.h | 1 |
10 files changed, 214 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, diff --git a/src/utils/string.c b/src/utils/string.c index e01d1b6..5f9b7de 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -1,4 +1,5 @@ #include "string.h" +#include "memory.h" #include <stdint.h> #include <string.h> @@ -30,3 +31,23 @@ uint64_t decimalToU64(char *str_begin, char *str_end, bool *success) { *success = true; return result; } + +char *u64ToString(uint64_t value) { + char *str = a404m_malloc(21 * sizeof(*str)); + size_t i = 0; + + do { + str[i] = (value % 10) + '0'; + value /= 10; + ++i; + } while (value != 0); + + for (size_t j = 0; j < i / 2; ++j) { + char tmp = str[j]; + str[j] = str[i - j - 1]; + str[i - j - 1] = tmp; + } + str[i] = '\0'; + + return a404m_realloc(str, (i + 1) * sizeof(*str)); +} diff --git a/src/utils/string.h b/src/utils/string.h index 7d0a5c8..8f92bc4 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -7,3 +7,4 @@ size_t searchInStringArray(const char *array[], size_t array_size, const char *str, size_t str_size); uint64_t decimalToU64(char *str_begin, char *str_end, bool *success); +char* u64ToString(uint64_t value); |