aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/tree_parser
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2024-09-22 19:34:43 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2024-09-22 19:34:43 +0330
commitf79290084948f3cf140395c270c07cf29ca58e8d (patch)
treed716526678782153f3617bbf78984b4c4ebed380 /src/compiler/tree_parser
parentd2ab53c625d386a4fbc6a9d5a5eb29faab1b3f0c (diff)
Better errors
Added variables
Diffstat (limited to 'src/compiler/tree_parser')
-rw-r--r--src/compiler/tree_parser/tree_parser.c695
-rw-r--r--src/compiler/tree_parser/tree_parser.h113
2 files changed, 808 insertions, 0 deletions
diff --git a/src/compiler/tree_parser/tree_parser.c b/src/compiler/tree_parser/tree_parser.c
new file mode 100644
index 0000000..cb1ef4c
--- /dev/null
+++ b/src/compiler/tree_parser/tree_parser.c
@@ -0,0 +1,695 @@
+#include "tree_parser.h"
+
+#include <compiler/error_helper/error_helper.h>
+#include <compiler/lexer/lexer.h>
+#include <compiler/parser/parser.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utils/memory/memory.h>
+
+#include "utils/types.h"
+
+const char *TREE_TOKEN_STRINGS[] = {
+ "TREE_TOKEN_NONE",
+ "TREE_TOKEN_GLOBAL_SCOPE",
+ "TREE_TOKEN_LOCAL_SCOPE",
+ "TREE_TOKEN_FUNCTION_CALL",
+ "TREE_TOKEN_DEFINE_VARIABLE",
+ "TREE_TOKEN_DEFINE_CONSTANT",
+ "TREE_TOKEN_IDENTIFIER",
+ "TREE_TOKEN_VALUE_STRING",
+ "TREE_TOKEN_STRUCT",
+ "TREE_TOKEN_FUNCTION",
+};
+
+void _printParsedTreeNode(const ParsedTree *parsedTree, int indent) {
+ if (parsedTree == NULL) {
+ for (int i = 0; i < indent; ++i) printf(" ");
+ printf("null\n");
+ }
+ printf("{token=%s", TREE_TOKEN_STRINGS[parsedTree->token]);
+ switch (parsedTree->token) {
+ case TREE_TOKEN_NONE:
+ goto RETURN_SUCCESS;
+ case TREE_TOKEN_GLOBAL_SCOPE:
+ case TREE_TOKEN_LOCAL_SCOPE:
+ case TREE_TOKEN_FUNCTION_CALL:
+ case TREE_TOKEN_DEFINE_VARIABLE:
+ case TREE_TOKEN_IDENTIFIER:
+ case TREE_TOKEN_VALUE_STRING:
+ case TREE_TOKEN_STRUCT:
+ case TREE_TOKEN_DEFINE_CONSTANT:
+ case TREE_TOKEN_FUNCTION:
+ }
+ fprintf(stderr, "bad parsed tree token %d at %s:%d", parsedTree->token,
+ __FILE_NAME__, __LINE__);
+ exit(1);
+RETURN_SUCCESS:
+ printf("}\n");
+};
+
+void printParsedTreeNode(const ParsedTree *parsedTree) {
+ _printParsedTreeNode(parsedTree, 0);
+}
+
+void deleteParsedTree(ParsedTree *parsedTree) {
+ if (parsedTree == NULL) {
+ return;
+ }
+ switch (parsedTree->token) {
+ case TREE_TOKEN_NONE:
+ goto RETURN_SUCCESS;
+ case TREE_TOKEN_GLOBAL_SCOPE:
+ case TREE_TOKEN_LOCAL_SCOPE: {
+ TreeScopeMetadata *metadata = parsedTree->metadata;
+ for (size_t i = 0; i < metadata->lines_size; ++i) {
+ deleteParsedTree(metadata->lines[i]);
+ }
+ free(metadata->lines);
+ free(metadata->variables);
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_FUNCTION_CALL: {
+ TreeFunctionCallMetadata *metadata = parsedTree->metadata;
+ for (size_t i = 0; i < metadata->values_size; ++i) {
+ deleteParsedTree(metadata->values[i]);
+ }
+ free(metadata->values);
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_DEFINE_VARIABLE:
+ case TREE_TOKEN_DEFINE_CONSTANT: {
+ TreeDefineVariableMetadata *metadata = parsedTree->metadata;
+ deleteParsedTree(metadata->value);
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_IDENTIFIER: {
+ TreeIdentifierMetadata *metadata = parsedTree->metadata;
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_VALUE_STRING: {
+ TreeStringValueMetadata *metadata = parsedTree->metadata;
+ free(metadata->str);
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_STRUCT: {
+ TreeStructMetadata *metadata = parsedTree->metadata;
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ case TREE_TOKEN_FUNCTION: {
+ TreeFunctionMetadata *metadata = parsedTree->metadata;
+ TreeScopeMetadata *scope = metadata->scope;
+ if (scope != NULL) {
+ for (size_t i = 0; i < scope->lines_size; ++i) {
+ deleteParsedTree(scope->lines[i]);
+ }
+ free(scope->lines);
+ free(scope->variables);
+ }
+ for (size_t i = 0; i < metadata->params_size; ++i) {
+ deleteParsedTree(metadata->params[i]->value);
+ free(metadata->params[i]);
+ }
+ free(metadata->params);
+ free(metadata);
+ goto RETURN_SUCCESS;
+ }
+ }
+ fprintf(stderr, "bad parsed tree token %d at %s:%d", parsedTree->token,
+ __FILE_NAME__, __LINE__);
+ exit(1);
+RETURN_SUCCESS:
+ free(parsedTree);
+}
+
+ParsedTree *treeParser(SourceCode code) {
+ ParsedNode *parsedNode = parser(code);
+ if (parsedNode == NULL) {
+ return NULL;
+ }
+ ParsedTree *tree= _treeParser(parsedNode, code);
+ deleteParsedNode(parsedNode);
+ return tree;
+}
+
+ParsedTree *_treeParser(const ParsedNode *node, SourceCode code) {
+ if (node->token == PARSED_TOKEN_ROOT) {
+ return treeParseRoot(node, code);
+ } else {
+ return NULL;
+ }
+}
+
+ParsedTree *treeParseNode(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ switch (node->token) {
+ case PARSED_TOKEN_ROOT:
+ case PARSED_TOKEN_NONE:
+ fprintf(stderr, "parsed token not allowed %s",
+ PARSED_TOKEN_STRINGS[node->token]);
+ return NULL;
+ case PARSED_TOKEN_EOL:
+ return treeParseNode((ParserEOLMetadata *)node->metadata, code, scopes,
+ scopes_size);
+ case PARSED_TOKEN_IDENTIFIER:
+ return treeParseIdentifier(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_FUNCTION_CALL:
+ return treeParseFunctionCall(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_COMMA:
+ return treeParseNode((ParserCommaMetadata *)node->metadata, code, scopes,
+ scopes_size);
+ case PARSED_TOKEN_PARENTHESIS:
+ return treeParseNode((ParserParenthesisMetadata *)node->metadata, code,
+ scopes, scopes_size);
+ case PARSED_TOKEN_CODE_BODY:
+ return treeParseLocalScope(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_VALUE_STRING:
+ return treeParseValueString(node, code);
+ case PARSED_TOKEN_DEFINE_VARIABLE:
+ return treeParseVariableDefinition(node, code, scopes, scopes_size,
+ TREE_TOKEN_DEFINE_VARIABLE);
+ case PARSED_TOKEN_DEFINE_CONSTANT:
+ return treeParseVariableDefinition(node, code, scopes, scopes_size,
+ TREE_TOKEN_DEFINE_CONSTANT);
+ case PARSED_TOKEN_STRUCT:
+ return treeParseStruct(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_FUNCTION:
+ return treeParseFunction(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_FUNCTION_PARAMS:
+ }
+ fprintf(stderr, "bad parsed token %d at %s:%d", node->token, __FILE_NAME__,
+ __LINE__);
+ return NULL;
+}
+
+ParsedTree *treeParseExpr(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ switch (node->token) {
+ case PARSED_TOKEN_ROOT:
+ case PARSED_TOKEN_NONE:
+ case PARSED_TOKEN_EOL:
+ case PARSED_TOKEN_COMMA:
+ case PARSED_TOKEN_DEFINE_VARIABLE:
+ case PARSED_TOKEN_DEFINE_CONSTANT:
+ case PARSED_TOKEN_CODE_BODY:
+ printError("Parsed token %s is not an expression", code, node->strBegin,
+ node->strEnd, PARSED_TOKEN_STRINGS[node->token]);
+ return NULL;
+ case PARSED_TOKEN_PARENTHESIS:
+ case PARSED_TOKEN_FUNCTION_CALL:
+ case PARSED_TOKEN_VALUE_STRING:
+ case PARSED_TOKEN_IDENTIFIER:
+ case PARSED_TOKEN_STRUCT:
+ case PARSED_TOKEN_FUNCTION:
+ return treeParseNode(node, code, scopes, scopes_size);
+ case PARSED_TOKEN_FUNCTION_PARAMS:
+ }
+ fprintf(stderr, "bad parsed token %d", node->token);
+ return NULL;
+}
+
+ParsedTree *treeParseRoot(const ParsedNode *node, SourceCode code) {
+ return treeParseLocalScope(node, code, NULL, 0);
+}
+
+ParsedTree *treeParseLocalScope(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ const ParserScopeMetadata *node_metadata = node->metadata;
+ ParsedNode **const operands = node_metadata->operands;
+ const size_t operands_size = node_metadata->operands_size;
+
+ ParsedTree *tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_LOCAL_SCOPE;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+
+ TreeScopeMetadata *metadata = tree->metadata =
+ a404m_malloc(sizeof(*metadata));
+
+ size_t metadata_variables_size = 0;
+ metadata->variables = a404m_malloc(metadata_variables_size *
+ sizeof(TreeDefineVariableMetadata *));
+ metadata->variables_size = 0;
+
+ size_t metadata_lines_size = 0;
+ metadata->lines = a404m_malloc(metadata_lines_size * sizeof(ParsedTree *));
+ metadata->lines_size = 0;
+
+ const size_t newScopes_size = scopes_size + 1;
+ const TreeScopeMetadata *newScopes[newScopes_size];
+
+ for (size_t i = 0; i < scopes_size; ++i) {
+ newScopes[i] = scopes[i];
+ }
+
+ newScopes[newScopes_size - 1] = metadata;
+
+ for (size_t i = 0; i < operands_size; ++i) {
+ const ParsedNode *operand = operands[i];
+ ParsedTree *const parsedTree =
+ treeParseNode(operand, code, newScopes, newScopes_size);
+ if (parsedTree == NULL) {
+ goto RETURN_ERROR;
+ }
+ switch (parsedTree->token) {
+ case TREE_TOKEN_DEFINE_CONSTANT:
+ case TREE_TOKEN_DEFINE_VARIABLE: {
+ TreeDefineVariableMetadata *const variableDefine = parsedTree->metadata;
+ if (variableDefine == NULL) {
+ goto RETURN_ERROR;
+ } else if (metadata->variables_size == metadata_variables_size) {
+ metadata_variables_size += metadata_variables_size / 2 + 1;
+ metadata->variables = a404m_realloc(
+ metadata->variables,
+ metadata_variables_size * sizeof(TreeDefineVariableMetadata *));
+ }
+ metadata->variables[metadata->variables_size] = variableDefine;
+ metadata->variables_size += 1;
+ }
+ /* fall through */
+ default:
+ if (metadata->lines_size == metadata_lines_size) {
+ metadata_lines_size += metadata_lines_size / 2 + 1;
+ metadata->lines = a404m_realloc(
+ metadata->lines, metadata_lines_size * sizeof(ParsedTree *));
+ }
+ metadata->lines[metadata->lines_size] = parsedTree;
+ metadata->lines_size += 1;
+ continue;
+ }
+ printError("'%s' Is not allowed here", code, operand->strBegin,
+ operand->strEnd, PARSED_TOKEN_STRINGS[operand->token]);
+ goto RETURN_ERROR;
+ }
+
+ metadata->variables =
+ a404m_realloc(metadata->variables, metadata->variables_size);
+
+ return tree;
+
+RETURN_ERROR:
+ free(tree);
+ free(metadata);
+ return NULL;
+}
+
+TreeDefineVariableMetadata *treeParseDefineVariable(
+ ParsedTree *tree, const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[], size_t scopes_size) {
+ TreeDefineVariableMetadata *define = a404m_malloc(sizeof(*define));
+ define->tree = tree;
+
+ ParserVariableDefineMetadata *metadata = node->metadata;
+
+ if (metadata->value == NULL) {
+ define->value = NULL;
+ } else if ((define->value = treeParseExpr(metadata->value, code, scopes,
+ scopes_size)) == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ if (metadata->name->token == PARSED_TOKEN_IDENTIFIER) {
+ define->nameBegin = metadata->name->strBegin;
+ define->nameEnd = metadata->name->strEnd;
+ } else {
+ printError("Names should be an identifier", code, metadata->name->strBegin,
+ metadata->name->strEnd);
+ goto RETURN_ERROR;
+ }
+
+ if (metadata->type == NULL) {
+ define->type = getTreeExpressionType(define->value);
+ } else if (metadata->type->token == PARSED_TOKEN_IDENTIFIER) {
+ const TreeDefineVariableMetadata *variable =
+ getVariable(metadata->type->strBegin, metadata->type->strEnd, code,
+ scopes, scopes_size);
+ if (variable == NULL) {
+ goto RETURN_ERROR;
+ }
+ define->type = getType(variable);
+ } else {
+ printError("Types should be an identifier (for now)", code,
+ metadata->type->strBegin, metadata->type->strEnd);
+ goto RETURN_ERROR;
+ }
+
+ if (define->type == NULL) {
+ printError("Can't specify type", code, node->strBegin, node->strEnd);
+ goto RETURN_ERROR;
+ }
+
+ return define;
+
+RETURN_ERROR:
+ free(define);
+ return NULL;
+}
+
+TreeDefineVariableMetadata *getVariable(const char *strBegin,
+ const char *strEnd, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ const size_t size = strEnd - strBegin;
+ const char *str = strBegin;
+
+ for (size_t i = 0; i < scopes_size; ++i) {
+ const TreeScopeMetadata *scope = scopes[i];
+ for (size_t j = scope->variables_size - 1; j != (typeof(j))-1; --j) {
+ TreeDefineVariableMetadata *variable = scope->variables[j];
+ const size_t variable_str_size = variable->nameEnd - variable->nameBegin;
+ if (size == variable_str_size &&
+ strncmp(str, variable->nameBegin, size) == 0) {
+ return variable;
+ }
+ }
+ }
+
+ printError("Identifier is not defined", code, strBegin, strEnd);
+ return NULL;
+}
+
+ParsedTree *treeParseIdentifier(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ TreeDefineVariableMetadata *variable =
+ getVariable(node->strBegin, node->strEnd, code, scopes, scopes_size);
+ if (variable != NULL) {
+ ParsedTree *tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_IDENTIFIER;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+ TreeIdentifierMetadata *metadata = tree->metadata =
+ a404m_malloc(sizeof(TreeIdentifierMetadata));
+ metadata->variable = variable;
+ return tree;
+ }
+ return NULL;
+}
+
+ParsedTree *treeParseFunctionCall(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ ParserFunctionCallMetadata *node_metadata = node->metadata;
+
+ ParsedTree *tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_FUNCTION_CALL;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+
+ TreeFunctionCallMetadata *metadata = tree->metadata =
+ a404m_malloc(sizeof(*metadata));
+
+ size_t metadata_values_size = 0;
+ metadata->values = a404m_malloc(metadata_values_size * sizeof(ParsedTree *));
+ metadata->values_size = 0;
+
+ TreeDefineVariableMetadata *variable =
+ getVariable(node_metadata->functionNameBegin,
+ node_metadata->functionNameEnd, code, scopes, scopes_size);
+
+ if (variable == NULL) {
+ goto RETURN_ERROR;
+ }
+ metadata->function = variable;
+
+ for (size_t i = 0; i < node_metadata->scope->operands_size; ++i) {
+ ParsedNode *const operand = node_metadata->scope->operands[i];
+ ParsedTree *const operandTree =
+ treeParseNode(operand, code, scopes, scopes_size);
+ if (operandTree == NULL) {
+ goto RETURN_ERROR;
+ }
+ // TODO: check types
+ if (metadata->values_size == metadata_values_size) {
+ metadata_values_size += metadata_values_size / 2 + 1;
+ metadata->values =
+ a404m_malloc(metadata_values_size * sizeof(ParsedTree *));
+ }
+ metadata->values[metadata->values_size] = operandTree;
+ metadata->values_size += 1;
+ }
+
+ metadata->values = a404m_realloc(
+ metadata->values, metadata->values_size * sizeof(ParsedTree *));
+ return tree;
+
+RETURN_ERROR:
+ free(metadata);
+ free(tree);
+ return NULL;
+}
+
+ParsedTree *treeParseValueString(const ParsedNode *node, SourceCode code) {
+ ParsedTree *const tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_VALUE_STRING;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+ if ((tree->metadata = nodeToString(node, code)) == NULL) {
+ free(tree);
+ return NULL;
+ }
+ return tree;
+}
+
+ParsedTree *treeParseVariableDefinition(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size, TreeToken token) {
+ ParsedTree *const tree = a404m_malloc(sizeof(*tree));
+ tree->token = token;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+ if ((tree->metadata = treeParseDefineVariable(tree, node, code, scopes,
+ scopes_size)) == NULL) {
+ free(tree);
+ return NULL;
+ }
+ return tree;
+}
+
+ParsedTree *treeParseStruct(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ const ParserStructMetadata *node_metadata = node->metadata;
+
+ ParsedTree *const tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_STRUCT;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+ TreeStructMetadata *const metadata = tree->metadata =
+ a404m_malloc(sizeof(*metadata));
+
+ if (node_metadata->body != NULL) {
+ const ParserScopeMetadata *node_body = node_metadata->body->metadata;
+ for (size_t i = 0; i < node_body->operands_size; ++i) {
+ // TODO: implement
+ printError("Not implemented", code, node->strBegin, node->strEnd);
+
+ free(metadata);
+ free(tree);
+ return NULL;
+ }
+ }
+
+ return tree;
+}
+
+ParsedTree *treeParseFunction(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size) {
+ const ParserFunctionMetadata *node_metadata = node->metadata;
+
+ ParsedTree *const tree = a404m_malloc(sizeof(*tree));
+ tree->token = TREE_TOKEN_FUNCTION;
+ tree->strBegin = node->strBegin;
+ tree->strEnd = node->strEnd;
+
+ TreeFunctionMetadata *const metadata = tree->metadata =
+ a404m_malloc(sizeof(*metadata));
+
+ ParsedTree *parsedTree =
+ treeParseNode(node_metadata->type, code, scopes, scopes_size);
+
+ if (parsedTree == NULL) {
+ goto RETURN_ERROR;
+ }
+ metadata->returnType = getTreeExpressionType(parsedTree);
+ // TODO: this is not right
+ deleteParsedTree(parsedTree);
+
+ const ParserScopeMetadata *params = node_metadata->params->metadata;
+
+ size_t metadata_params_size = 0;
+ metadata->params =
+ a404m_malloc(metadata_params_size * sizeof(TreeDefineVariableMetadata *));
+ metadata->params_size = 0;
+
+ for (size_t i = 0; i < params->operands_size; ++i) {
+ const ParsedNode *operand = params->operands[i];
+ TreeDefineVariableMetadata *define =
+ treeParseDefineVariable(tree, operand, code, scopes, scopes_size);
+ if (define == NULL) {
+ goto RETURN_ERROR;
+ }
+ if (metadata->params_size == metadata_params_size) {
+ metadata_params_size += metadata_params_size / 2 + 1;
+ metadata->params = a404m_realloc(
+ metadata->params,
+ metadata_params_size * sizeof(TreeDefineVariableMetadata *));
+ }
+ metadata->params[metadata->params_size] = define;
+ metadata->params_size += 1;
+ }
+ metadata->params =
+ a404m_realloc(metadata->params, metadata->params_size *
+ sizeof(TreeDefineVariableMetadata *));
+
+ if (node_metadata->body != NULL) {
+ printError("Not implemented", code, node->strBegin, node->strEnd);
+
+ free(metadata);
+ free(tree);
+ return NULL;
+ } else {
+ metadata->scope = NULL;
+ }
+
+ return tree;
+RETURN_ERROR:
+
+ free(metadata);
+ free(tree);
+ return NULL;
+}
+
+TypeId getTreeExpressionType(ParsedTree *tree) {
+ switch (tree->token) {
+ case TREE_TOKEN_FUNCTION_CALL:
+ return ((TreeFunctionMetadata *)((TreeFunctionCallMetadata *)
+ tree->metadata)
+ ->function->type->metadata)
+ ->returnType;
+ case TREE_TOKEN_DEFINE_VARIABLE:
+ case TREE_TOKEN_DEFINE_CONSTANT:
+ return ((TreeDefineVariableMetadata *)tree->metadata)->type;
+ case TREE_TOKEN_IDENTIFIER:
+ return getType(((TreeIdentifierMetadata *)tree->metadata)->variable);
+ case TREE_TOKEN_VALUE_STRING:
+ case TREE_TOKEN_STRUCT:
+ case TREE_TOKEN_GLOBAL_SCOPE:
+ case TREE_TOKEN_LOCAL_SCOPE:
+ case TREE_TOKEN_FUNCTION: // TODO: find a better way for function
+ return tree;
+ case TREE_TOKEN_NONE:
+ }
+ fprintf(stderr, "bad parsed tree token %d at %d:%s", tree->token, __LINE__,
+ __FILE_NAME__);
+ exit(1);
+}
+
+TypeId getType(const TreeDefineVariableMetadata *define) {
+ if (define->value == NULL || !isType(define->value)) {
+ return define->type;
+ } else {
+ return define->tree;
+ }
+}
+
+bool isType(ParsedTree *const tree) {
+ switch (tree->token) {
+ case TREE_TOKEN_FUNCTION_CALL:
+ case TREE_TOKEN_DEFINE_VARIABLE:
+ case TREE_TOKEN_DEFINE_CONSTANT:
+ case TREE_TOKEN_IDENTIFIER:
+ case TREE_TOKEN_VALUE_STRING:
+ case TREE_TOKEN_GLOBAL_SCOPE:
+ case TREE_TOKEN_LOCAL_SCOPE:
+ return false;
+ case TREE_TOKEN_STRUCT:
+ case TREE_TOKEN_FUNCTION: // TODO: find a better way for function
+ return true;
+ case TREE_TOKEN_NONE:
+ }
+ fprintf(stderr, "bad parsed tree token %d at %d:%s", tree->token, __LINE__,
+ __FILE_NAME__);
+ exit(1);
+}
+
+SizedString *nodeToString(ParsedNode const *tree, SourceCode code) {
+ const char *strBegin = tree->strBegin + 1;
+ const char *strEnd = tree->strEnd - 1;
+
+ char *str = a404m_malloc((strEnd - strBegin + 1) * sizeof(char));
+ size_t inserted = 0;
+
+ for (char const *iter = strBegin; iter < strEnd; ++iter) {
+ char c = *iter;
+ if (c == '\\') {
+ if (++iter < strEnd) {
+ switch (*iter) {
+ case '\'':
+ c = '\'';
+ break;
+ case '\"':
+ c = '\"';
+ break;
+ case '\\':
+ c = '\\';
+ break;
+ case 'a':
+ c = '\a';
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ /*case 'u':*/ // TODO: do it
+ /* c = '';*/
+ /* break;*/
+ default:
+ printError("Bad escape code '\\%s'", code, tree->strBegin,
+ tree->strEnd, *iter);
+ goto RETURN_ERROR;
+ }
+ } else {
+ printError("Expected character after '\\'", code, tree->strBegin,
+ tree->strEnd);
+ goto RETURN_ERROR;
+ }
+ }
+ str[inserted] = c;
+ ++inserted;
+ }
+
+ str[inserted] = '\0';
+ SizedString *const string = a404m_malloc(sizeof(SizedString));
+ string->str = a404m_realloc(str, (inserted + 1) * sizeof(char));
+ string->size = inserted;
+ return string;
+RETURN_ERROR:
+ free(str);
+ return NULL;
+}
diff --git a/src/compiler/tree_parser/tree_parser.h b/src/compiler/tree_parser/tree_parser.h
new file mode 100644
index 0000000..0ee783f
--- /dev/null
+++ b/src/compiler/tree_parser/tree_parser.h
@@ -0,0 +1,113 @@
+#pragma once
+
+#include <compiler/parser/parser.h>
+
+#include "utils/types.h"
+
+typedef enum TreeToken {
+ TREE_TOKEN_NONE = 0,
+ TREE_TOKEN_GLOBAL_SCOPE,
+ TREE_TOKEN_LOCAL_SCOPE,
+ TREE_TOKEN_FUNCTION_CALL,
+ TREE_TOKEN_DEFINE_VARIABLE,
+ TREE_TOKEN_DEFINE_CONSTANT,
+ TREE_TOKEN_IDENTIFIER,
+ TREE_TOKEN_VALUE_STRING,
+ TREE_TOKEN_STRUCT,
+ TREE_TOKEN_FUNCTION,
+} TreeToken;
+
+extern const char *TREE_TOKEN_STRINGS[];
+
+typedef struct ParsedTree {
+ char const *strBegin;
+ char const *strEnd;
+ TreeToken token;
+ void *metadata;
+} ParsedTree;
+
+typedef struct TreeStructMetadata {
+} TreeStructMetadata;
+
+typedef ParsedTree *TypeId;
+
+typedef struct TreeDefineVariableMetadata {
+ char const *nameBegin;
+ char const *nameEnd;
+ TypeId type;
+ ParsedTree *value;
+ ParsedTree *tree;
+} TreeDefineVariableMetadata;
+
+typedef struct TreeFunctionCallMetadata {
+ TreeDefineVariableMetadata *function;
+ ParsedTree **values;
+ size_t values_size;
+} TreeFunctionCallMetadata;
+
+typedef struct TreeScopeMetadata {
+ ParsedTree **lines;
+ size_t lines_size;
+ TreeDefineVariableMetadata **variables;
+ size_t variables_size;
+} TreeScopeMetadata;
+
+typedef struct TreeIdentifierMetadata {
+ TreeDefineVariableMetadata *variable;
+} TreeIdentifierMetadata;
+
+typedef struct TreeFunctionMetadata {
+ TreeDefineVariableMetadata **params;
+ size_t params_size;
+ TreeScopeMetadata *scope;
+ TypeId returnType;
+} TreeFunctionMetadata;
+
+typedef SizedString TreeStringValueMetadata;
+
+extern void _printParsedTreeNode(const ParsedTree *parsedTree,int indent);
+extern void printParsedTreeNode(const ParsedTree *parsedTree);
+
+extern void deleteParsedTree(ParsedTree *parsedTree);
+
+extern ParsedTree *treeParser(SourceCode code);
+extern ParsedTree *_treeParser(const ParsedNode *node, SourceCode code);
+
+extern ParsedTree *treeParseNode(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+
+extern ParsedTree *treeParseRoot(const ParsedNode *root, SourceCode code);
+extern ParsedTree *treeParseLocalScope(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+
+extern TreeDefineVariableMetadata *treeParseDefineVariable(
+ ParsedTree *tree, const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[], size_t scopes_size);
+extern TreeDefineVariableMetadata *getVariable(
+ const char *strBegin, const char *strEnd, SourceCode code,
+ const TreeScopeMetadata *scopes[], size_t scopes_size);
+extern ParsedTree *treeParseIdentifier(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+extern ParsedTree *treeParseFunctionCall(const ParsedNode *node,
+ SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+extern ParsedTree *treeParseValueString(const ParsedNode *node,
+ SourceCode code);
+extern ParsedTree *treeParseVariableDefinition(
+ const ParsedNode *node, SourceCode code, const TreeScopeMetadata *scopes[],
+ size_t scopes_size, TreeToken token);
+extern ParsedTree *treeParseStruct(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+extern ParsedTree *treeParseFunction(const ParsedNode *node, SourceCode code,
+ const TreeScopeMetadata *scopes[],
+ size_t scopes_size);
+
+extern TypeId getTreeExpressionType(ParsedTree *const tree);
+extern TypeId getType(const TreeDefineVariableMetadata *define);
+extern bool isType(ParsedTree *const tree);
+extern SizedString *nodeToString(ParsedNode const *tree, SourceCode code);