#include "tree_parser.h" #include #include #include #include const char *TREE_TOKEN_STRINGS[] = { "TREE_TOKEN_NONE", "TREE_TOKEN_ROOT", "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", }; static void _printParsedTreeVariable(const TreeDefineVariableMetadata *variable, int indent) { if (variable == NULL) { for (int i = 0; i < indent; ++i) printf(" "); printf("null\n"); return; } for (int i = 0; i < indent; ++i) printf(" "); printf("{name='%.*s',type=%p,value=\n", (int)(variable->nameEnd - variable->nameBegin), variable->nameBegin, variable->type); _printParsedTreeNode(variable->value, indent + 1); for (int i = 0; i < indent; ++i) printf(" "); printf("}\n"); } void _printParsedTreeNode(const ParsedTree *parsedTree, int indent) { for (int i = 0; i < indent; ++i) printf(" "); if (parsedTree == NULL) { printf("null\n"); return; } printf("{token=%s", TREE_TOKEN_STRINGS[parsedTree->token]); switch (parsedTree->token) { case TREE_TOKEN_NONE: goto RETURN_SUCCESS; case TREE_TOKEN_ROOT: case TREE_TOKEN_GLOBAL_SCOPE: case TREE_TOKEN_LOCAL_SCOPE: { const TreeScopeMetadata *metadata = parsedTree->metadata; for (int i = 0; i < indent; ++i) printf(" "); printf(",lines=\n"); for (size_t i = 0; i < metadata->lines_size; ++i) { _printParsedTreeNode(metadata->lines[i], indent + 1); } for (int i = 0; i < indent; ++i) printf(" "); printf(",variables=\n"); for (size_t i = 0; i < metadata->variables_size; ++i) { _printParsedTreeVariable(metadata->variables[i], indent + 1); } goto RETURN_SUCCESS; } case TREE_TOKEN_FUNCTION_CALL: { const TreeFunctionCallMetadata *metadata = parsedTree->metadata; printf(",lines=\n"); for (size_t i = 0; i < metadata->values_size; ++i) { _printParsedTreeNode(metadata->values[i], indent + 1); } goto RETURN_SUCCESS; } case TREE_TOKEN_DEFINE_VARIABLE: case TREE_TOKEN_DEFINE_CONSTANT: { const TreeDefineVariableMetadata *metadata = parsedTree->metadata; printf(",define=\n"); _printParsedTreeVariable(metadata, indent + 1); goto RETURN_SUCCESS; } case TREE_TOKEN_IDENTIFIER: { const TreeIdentifierMetadata *metadata = parsedTree->metadata; printf(",variable=\n"); _printParsedTreeVariable(metadata->variable, indent + 1); goto RETURN_SUCCESS; } case TREE_TOKEN_VALUE_STRING: { const TreeStringValueMetadata *metadata = parsedTree->metadata; printf(",str='%.*s'\n", (int)metadata->size, metadata->str); goto RETURN_SUCCESS; } case TREE_TOKEN_STRUCT: { const TreeStructMetadata *metadata = parsedTree->metadata; printf(",metadata=%p\n", metadata); goto RETURN_SUCCESS; } case TREE_TOKEN_FUNCTION: { const TreeFunctionMetadata *metadata = parsedTree->metadata; const TreeScopeMetadata *scope = metadata->scope; printf(",scope=\n"); if (scope != NULL) { for (int i = 0; i < indent; ++i) printf(" "); printf(",lines=\n"); for (size_t i = 0; i < scope->lines_size; ++i) { _printParsedTreeNode(scope->lines[i], indent + 1); } for (int i = 0; i < indent; ++i) printf(" "); printf(",variables=\n"); for (size_t i = 0; i < scope->variables_size; ++i) { _printParsedTreeVariable(scope->variables[i], indent + 1); } } else { for (int i = 0; i < indent; ++i) printf(" "); printf("null\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf(",params=\n"); for (size_t i = 0; i < metadata->params_size; ++i) { _printParsedTreeVariable(metadata->params[i], indent + 1); } goto RETURN_SUCCESS; } } fprintf(stderr, "bad parsed tree token %d at %s:%d", parsedTree->token, __FILE_NAME__, __LINE__); exit(1); RETURN_SUCCESS: for (int i = 0; i < indent; ++i) printf(" "); 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_ROOT: 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); free(scope); } 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) { ParserScopeMetadata *scope = a404m_malloc(sizeof(*scope)); scope->operands_size = 0; scope->operands = a404m_malloc(scope->operands_size * sizeof(ParsedNode *)); ParsedNode *const parsedNode = newParsedNode(NULL, NULL, PARSED_TOKEN_ROOT, scope, NULL); for (size_t i = 0; i < code->size; ++i) { ParsedNode *const nParsedNode = parser(code, i); if (nParsedNode == NULL) { goto RETURN_ERROR; } ParserScopeMetadata *const nscope = nParsedNode->metadata; for (size_t j = 0; j < nscope->operands_size; ++j) { size_t scopeSize = a404m_malloc_usable_size(scope->operands) / sizeof(ParsedNode *); if (scopeSize == scope->operands_size) { scopeSize += scopeSize / 2 + 1; scope->operands = a404m_realloc(scope->operands, scopeSize * sizeof(ParsedNode *)); } scope->operands[scope->operands_size] = nscope->operands[j]; scope->operands_size += 1; } free(nscope->operands); nscope->operands = NULL; nscope->operands_size = 0; deleteParsedNode(nParsedNode); } ParsedTree *tree = _treeParser(parsedNode, code); deleteParsedNode(parsedNode); return tree; RETURN_ERROR: deleteParsedNode(parsedNode); return NULL; } ParsedTree *treeParserWithPrint(SourceCode *code) { ParserScopeMetadata *scope = a404m_malloc(sizeof(*scope)); scope->operands_size = 0; scope->operands = a404m_malloc(scope->operands_size * sizeof(ParsedNode *)); ParsedNode *const parsedNode = newParsedNode(NULL, NULL, PARSED_TOKEN_ROOT, scope, NULL); for (size_t i = 0; i < code->size; ++i) { ParsedNode *const nParsedNode = parserWithPrint(code, i); if (nParsedNode == NULL) { fprintf(stderr, "Error in parser"); goto RETURN_ERROR; } printf("----parsed '%s'\n", code->codes[i]->filePath); printParsedNode(parsedNode); ParserScopeMetadata *const nscope = nParsedNode->metadata; for (size_t j = 0; j < nscope->operands_size; ++j) { size_t scopeSize = a404m_malloc_usable_size(scope->operands) / sizeof(ParsedNode *); if (scopeSize == scope->operands_size) { scopeSize += scopeSize / 2 + 1; scope->operands = a404m_realloc(scope->operands, scopeSize * sizeof(ParsedNode *)); } scope->operands[scope->operands_size] = nscope->operands[j]; scope->operands_size += 1; } free(nscope->operands); nscope->operands = NULL; nscope->operands_size = 0; deleteParsedNode(nParsedNode); } ParsedTree *tree = _treeParser(parsedNode, code); deleteParsedNode(parsedNode); return tree; RETURN_ERROR: deleteParsedNode(parsedNode); return NULL; } 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, 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_IMPORT: return treeParseImport(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, 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: case PARSED_TOKEN_IMPORT: 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, 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)); metadata->variables = a404m_malloc(0); metadata->variables_size = 0; metadata->lines = a404m_malloc(0); metadata->lines_size = 0; const size_t newScopes_size = scopes_size + 1; TreeScopeMetadata *newScopes[newScopes_size]; memcpy(newScopes, scopes, scopes_size * sizeof(TreeScopeMetadata *)); newScopes[newScopes_size - 1] = metadata; for (size_t i = 0; i < operands_size; ++i) { const ParsedNode *const operand = operands[i]; ParsedTree *const parsedTree = treeParseNode(operand, code, newScopes, newScopes_size); if (parsedTree == NULL) { goto RETURN_ERROR; } if (parsedTree->token != TREE_TOKEN_ROOT) { pushLineToScope(metadata, parsedTree); } else { 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 * sizeof(TreeDefineVariableMetadata *)); return tree; RETURN_ERROR: free(tree); free(metadata); return NULL; } TreeDefineVariableMetadata *treeParseDefineVariable(ParsedTree *tree, const ParsedNode *node, SourceCode *code, TreeScopeMetadata *scopes[], size_t scopes_size) { TreeDefineVariableMetadata *define = a404m_malloc(sizeof(*define)); define->tree = tree; const ParserVariableDefineMetadata *node_metadata = node->metadata; if (node_metadata->value == NULL) { define->value = NULL; } else if ((define->value = treeParseExpr(node_metadata->value, code, scopes, scopes_size)) == NULL) { goto RETURN_ERROR; } if (node_metadata->name->token == PARSED_TOKEN_IDENTIFIER) { define->nameBegin = node_metadata->name->strBegin; define->nameEnd = node_metadata->name->strEnd; } else { printError("Names should be an identifier", code, node_metadata->name->strBegin, node_metadata->name->strEnd); goto RETURN_ERROR; } if (node_metadata->type == NULL) { define->type = getTreeExpressionType(define->value); } else if (node_metadata->type->token == PARSED_TOKEN_IDENTIFIER) { const TreeDefineVariableMetadata *variable = getVariable(node_metadata->type->strBegin, node_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, node_metadata->type->strBegin, node_metadata->type->strEnd); goto RETURN_ERROR; } if (define->type == NULL) { printError("Can't specify type", code, node->strBegin, node->strEnd); goto RETURN_ERROR; } pushVariableToScope(scopes[scopes_size - 1], define); return define; RETURN_ERROR: free(define); return NULL; } TreeDefineVariableMetadata *getVariable(const char *strBegin, const char *strEnd, SourceCode *code, 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) { 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, 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, 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, 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, TreeScopeMetadata *[], size_t) { 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, 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); const size_t newScopes_size = scopes_size + 1; TreeScopeMetadata *newScopes[newScopes_size]; metadata->params = a404m_malloc(0); metadata->params_size = 0; metadata->scope = a404m_malloc(sizeof(*metadata->scope)); metadata->scope->variables = a404m_malloc(0); metadata->scope->variables_size = 0; metadata->scope->lines = a404m_malloc(0); metadata->scope->lines_size = 0; memcpy(newScopes, scopes, scopes_size * sizeof(TreeScopeMetadata *)); newScopes[newScopes_size - 1] = metadata->scope; if (parsedTree == NULL) { goto RETURN_ERROR; } metadata->returnType = getTreeExpressionType(parsedTree); // TODO: this is not right deleteParsedTree(parsedTree); const ParserScopeMetadata *params = node_metadata->params->metadata; for (size_t i = 0; i < params->operands_size; ++i) { const ParsedNode *operand = params->operands[i]; if (operand->token == PARSED_TOKEN_COMMA) { operand = (ParserCommaMetadata *)operand->metadata; } if (operand->token != PARSED_TOKEN_DEFINE_VARIABLE) { printError( "Only variable definition is allowed in function parameter list", code, operand->strBegin, operand->strEnd); } TreeDefineVariableMetadata *define = treeParseDefineVariable(tree, operand, code, newScopes, newScopes_size); if (define == NULL) { goto RETURN_ERROR; } size_t metadata_params_size = a404m_malloc_usable_size(metadata->params) / sizeof(ParserScopeMetadata *); 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) { const ParserScopeMetadata *body = node_metadata->body->metadata; for (size_t i = 0; i < body->operands_size; ++i) { ParsedTree *parsedTree = treeParseNode(body->operands[i], code, newScopes, newScopes_size); if (parsedTree == NULL) { goto RETURN_ERROR; } pushLineToScope(metadata->scope, parsedTree); } } else { free(metadata->scope->lines); metadata->scope->lines_size = 0; } return tree; RETURN_ERROR: // TODO: doesn't delete all of them free(metadata); free(tree); return NULL; } ParsedTree *treeParseImport(const ParsedNode *node, SourceCode *code, TreeScopeMetadata *[], size_t) { const ParserImportMetadata *node_metadata = node->metadata; SizedString *const path = nodeToString(node_metadata, code); if (path == NULL) { return NULL; } Code *const fileCode = read_whole_file(path->str); if (fileCode == NULL) { goto RETURN_ERROR; } pushToSourceCode(code, fileCode); ParsedNode *parsedNode = parser(code, code->size - 1); if (parsedNode == NULL) { goto RETURN_ERROR; } return _treeParser(parsedNode, code); RETURN_ERROR: free(path->str); free(path); 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: case TREE_TOKEN_ROOT: } 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: case TREE_TOKEN_ROOT: return false; case TREE_TOKEN_STRUCT: case TREE_TOKEN_FUNCTION: // TODO: find a better way for function return true; case TREE_TOKEN_NONE: break; } fprintf(stderr, "bad parsed tree token %d at %d:%s", tree->token, __LINE__, __FILE_NAME__); exit(1); } SizedString *nodeToString(ParsedNode const *node, SourceCode *code) { const char *strBegin = node->strBegin + 1; const char *strEnd = node->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 'h': { if (iter + 2 >= strEnd) { printError("Expected 2 hex characters after '\\c'", code, node->strBegin, node->strEnd); goto RETURN_ERROR; } bool isRight; c = hexToInt(iter + 1, iter + 3, &isRight); if (!isRight) { printError("Bad hex number", code, iter + 1, iter + 3); goto RETURN_ERROR; } iter += 2; break; } default: printError("Bad escape code '\\%s'", code, node->strBegin, node->strEnd, *iter); goto RETURN_ERROR; } } else { printError("Expected character after '\\'", code, node->strBegin, node->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; } uint64_t hexToInt(char const *begin, char const *end, bool *isRight) { uint64_t value = 0; for (char const *iter = begin; iter < end; ++iter) { value *= 16; const char c = *iter; if ('0' <= c && c <= '9') { value += c - '0'; } else if ('A' <= c && c <= 'F') { value += c - 'A' + 10; } else if ('a' <= c && c <= 'f') { value += c - 'a' + 10; } else { *isRight = false; return value; } } *isRight = true; return value; } void pushVariableToScope(TreeScopeMetadata *scope, TreeDefineVariableMetadata *variable) { size_t scope_variables_size = a404m_malloc_usable_size(scope->variables) / sizeof(TreeDefineVariableMetadata *); if (scope->variables_size == scope_variables_size) { scope_variables_size += scope_variables_size / 2 + 1; scope->variables = a404m_realloc( scope->variables, scope_variables_size * sizeof(TreeDefineVariableMetadata *)); } scope->variables[scope->variables_size] = variable; scope->variables_size += 1; } void pushLineToScope(TreeScopeMetadata *scope, ParsedTree *line) { size_t scope_lines_size = a404m_malloc_usable_size(scope->lines) / sizeof(ParsedTree *); if (scope->lines_size == scope_lines_size) { scope_lines_size += scope_lines_size / 2 + 1; scope->lines = a404m_realloc(scope->lines, scope_lines_size * sizeof(ParsedTree *)); } scope->lines[scope->lines_size] = line; scope->lines_size += 1; }