From b945815a225c3efdef5df03af52f921f98f9ed90 Mon Sep 17 00:00:00 2001 From: A404M Date: Sat, 25 Jan 2025 20:53:59 +0330 Subject: add function call --- src/compiler/ast-tree.c | 133 ++++++++++++++++++++++++++++++++++++++++-- src/compiler/ast-tree.h | 20 +++++++ src/compiler/code-generator.c | 59 +++++++++++++++---- src/compiler/code-generator.h | 14 ++++- src/compiler/parser.c | 109 ++++++++++++++++++++++++++-------- src/compiler/parser.h | 9 ++- 6 files changed, 300 insertions(+), 44 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 0a8811c..8cbfaf5 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -4,6 +4,7 @@ #include "utils/memory.h" #include #include +#include const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_FUNCTION", "AST_TREE_TOKEN_KEYWORD_PRINT", @@ -71,6 +72,33 @@ void astTreePrint(const AstTree *tree, int indent) { printf("]"); } goto RETURN_SUCCESS; + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTreeFunctionCall *metadata = tree->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("function=\n"); + astTreePrint(metadata->function, indent + 1); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("paramters=[\n"); + for (size_t i = 0; i < metadata->parameters_size; ++i) { + astTreePrint(metadata->parameters[i], indent + 1); + printf(",\n"); + } + for (int i = 0; i < indent; ++i) + printf(" "); + printf("]"); + } + goto RETURN_SUCCESS; + case AST_TREE_TOKEN_IDENTIFIER: { + AstTreeIdentifier *metadata = tree->metadata; + printf(",variable.name=%.*s", + (int)(metadata->name_end - metadata->name_begin), + metadata->name_begin); + } + goto RETURN_SUCCESS; case AST_TREE_TOKEN_NONE: } @@ -105,6 +133,7 @@ void astTreeDestroy(AstTree tree) { return; case AST_TREE_TOKEN_KEYWORD_PRINT: case AST_TREE_TOKEN_TYPE_VOID: + case AST_TREE_TOKEN_IDENTIFIER: return; case AST_TREE_TOKEN_TYPE_FUNCTION: { AstTreeTypeFunction *metadata = tree.metadata; @@ -116,6 +145,15 @@ void astTreeDestroy(AstTree tree) { free(metadata); } return; + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTreeFunctionCall *metadata = tree.metadata; + for (size_t i = 0; i < metadata->parameters_size; ++i) { + astTreeDelete(metadata->parameters[i]); + } + free(metadata->parameters); + free(metadata); + } + return; case AST_TREE_TOKEN_NONE: break; } @@ -182,9 +220,14 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { ParserNode *node = (ParserNodeEOLMetadata *)nodes->data[i]->metadata; ParserNodeVariableMetadata *node_metadata = node->metadata; - AstTree *type = astTreeParse(node_metadata->type, &root->variables, 1); - if (type == NULL) { - goto RETURN_ERROR; + AstTree *type; + if (node_metadata->type != NULL) { + type = astTreeParse(node_metadata->type, &root->variables, 1); + if (type == NULL) { + goto RETURN_ERROR; + } + } else { + type = NULL; // TODO: change this to find type } AstTree *value = astTreeParse(node_metadata->value, &root->variables, 1); @@ -192,7 +235,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { goto RETURN_ERROR; } - if (!hasTypeOf(value, type)) { + // TODO: then delete type != NULL + if (type != NULL && !hasTypeOf(value, type)) { printLog("Type mismatch"); goto RETURN_ERROR; } @@ -220,6 +264,24 @@ void pushVariable(AstTreeVariables *variables, size_t *variables_size, variables->size += 1; } +AstTreeVariable *getVariable(AstTreeVariables *variables, size_t variables_size, + char *name_begin, char *name_end) { + for (size_t i = 0; i < variables_size; ++i) { + AstTreeVariables vars = variables[i]; + for (size_t j = 0; j < vars.size; ++j) { + char *var_begin = vars.data[j]->name_begin; + char *var_end = vars.data[j]->name_end; + + if (name_end - name_begin == var_end - var_begin && + strncmp(var_begin, name_begin, name_end - name_begin) == 0) { + return vars.data[j]; + } + } + } + + return NULL; +} + AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables, size_t variables_size) { switch (parserNode->token) { @@ -231,12 +293,15 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables, return astTreeParseTypeFunction(parserNode, variables, variables_size); case PARSER_TOKEN_TYPE_VOID: return newAstTree(AST_TREE_TOKEN_TYPE_VOID, NULL); + case PARSER_TOKEN_FUNCTION_CALL: + return astTreeParseFunctionCall(parserNode, variables, variables_size); + case PARSER_TOKEN_IDENTIFIER: + return astTreeParseIdentifier(parserNode, variables, variables_size); case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_CONSTANT: - case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_NONE: case PARSER_TOKEN_ROOT: } @@ -390,6 +455,60 @@ RETURN_ERROR: return NULL; } +AstTree *astTreeParseFunctionCall(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size) { + ParserNodeFunctionCall *node_metadata = parserNode->metadata; + AstTree *function = + astTreeParse(node_metadata->function, variables, variables_size); + if (function == NULL) { + return NULL; + } + if (function->token != AST_TREE_TOKEN_IDENTIFIER) { + printLog("Not yet supported"); + return NULL; + } + // TODO: check types here + + AstTreeFunctionCall *metadata = a404m_malloc(sizeof(*metadata)); + metadata->function = function; + + metadata->parameters = + a404m_malloc(sizeof(*metadata->parameters) * node_metadata->params->size); + metadata->parameters_size = node_metadata->params->size; + + for (size_t i = 0; i < metadata->parameters_size; ++i) { + printLog("Not impelemented yet"); + exit(1); + if ((metadata->parameters[i] = astTreeParse(node_metadata->params->data[i], + variables, variables_size)) == + NULL || + hasTypeOf(metadata->parameters[i], function->metadata)) { + goto RETURN_ERROR; + } + } + + return newAstTree(AST_TREE_TOKEN_FUNCTION_CALL, metadata); +RETURN_ERROR: + for (size_t i = 0; i < metadata->parameters_size; ++i) { + astTreeDelete(metadata->parameters[i]); + } + free(metadata->parameters); + return NULL; +} + +AstTree *astTreeParseIdentifier(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size) { + AstTreeVariable *var = getVariable( + variables, variables_size, parserNode->str_begin, parserNode->str_end); + if (var == NULL) { + printLog("Variable not found"); + return NULL; + } + return newAstTree(AST_TREE_TOKEN_IDENTIFIER, (AstTreeIdentifier *)var); +} + bool hasTypeOf(AstTree *value, AstTree *type) { switch (type->token) { case AST_TREE_TOKEN_TYPE_FUNCTION: @@ -411,6 +530,8 @@ bool hasTypeOf(AstTree *value, AstTree *type) { case AST_TREE_TOKEN_KEYWORD_PRINT: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: + case AST_TREE_TOKEN_FUNCTION_CALL: + case AST_TREE_TOKEN_IDENTIFIER: return false; case AST_TREE_TOKEN_NONE: } @@ -418,6 +539,8 @@ bool hasTypeOf(AstTree *value, AstTree *type) { case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT: case AST_TREE_TOKEN_TYPE_VOID: + case AST_TREE_TOKEN_FUNCTION_CALL: + case AST_TREE_TOKEN_IDENTIFIER: return false; case AST_TREE_TOKEN_NONE: } diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index 23f0b9c..ae97ca2 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -8,6 +8,8 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_KEYWORD_PRINT, AST_TREE_TOKEN_TYPE_FUNCTION, AST_TREE_TOKEN_TYPE_VOID, + AST_TREE_TOKEN_FUNCTION_CALL, + AST_TREE_TOKEN_IDENTIFIER, AST_TREE_TOKEN_NONE, } AstTreeToken; @@ -52,6 +54,14 @@ typedef struct AstTreeTypeFunction { AstTree *returnType; } AstTreeTypeFunction; +typedef struct AstTreeFunctionCall { + AstTree *function; + AstTree **parameters; + size_t parameters_size; +} AstTreeFunctionCall; + +typedef AstTreeVariable AstTreeIdentifier; + extern const char *AST_TREE_TOKEN_STRINGS[]; void astTreePrint(const AstTree *tree, int indent); @@ -67,6 +77,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot); void pushVariable(AstTreeVariables *variables, size_t *variables_size, AstTreeVariable *variable); +AstTreeVariable *getVariable(AstTreeVariables *variables, size_t variables_size, + char *name_begin, char *name_end); AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables, size_t variables_size); @@ -79,5 +91,13 @@ AstTree *astTreeParseTypeFunction(ParserNode *parserNode, AstTreeVariables *variables, size_t variables_size); +AstTree *astTreeParseFunctionCall(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size); + +AstTree *astTreeParseIdentifier(ParserNode *parserNode, + AstTreeVariables *variables, + size_t variables_size); + bool hasTypeOf(AstTree *value, AstTree *type); bool typeIsEqual(AstTree *type0, AstTree *type1); diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c index 035a471..c07bab5 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 #include #include #include @@ -15,11 +16,13 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) { } CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end, - CodeGeneratorInstruction instruction) { + CodeGeneratorInstruction instruction, + void *metadata) { CodeGeneratorCode code = { .label_begin = label_begin, .label_end = label_end, .instruction = instruction, + .metadata = metadata, }; return code; } @@ -55,19 +58,19 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) { AstTreeVariable *variable = astTreeRoot->variables.data[i]; switch (variable->value->token) { case AST_TREE_TOKEN_FUNCTION: - codeGeneratorAstTreeFunction(variable->name_begin, variable->name_end, - *variable->value, codes); + if (!codeGeneratorAstTreeFunction(variable->name_begin, + variable->name_end, *variable->value, + codes)) { + return NULL; + } continue; case AST_TREE_TOKEN_KEYWORD_PRINT: - generateCodePushCode( - codes, - createGenerateCode(NULL, NULL, CODE_GENERATOR_INSTRUCTION_PRINT)); - continue; case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_NONE: } printLog("Bad token %d", variable->value->token); + return NULL; } return codes; @@ -84,8 +87,30 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, case AST_TREE_TOKEN_KEYWORD_PRINT: generateCodePushCode( codes, createGenerateCode(label_begin, label_end, - CODE_GENERATOR_INSTRUCTION_PRINT)); + CODE_GENERATOR_INSTRUCTION_PRINT, NULL)); + goto OK; + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTreeFunctionCall *metadata = tree.metadata; + AstTree *function = metadata->function; + if (metadata->parameters_size != 0) { + printLog("Not implemented"); + exit(0); + } + if (function->token != AST_TREE_TOKEN_IDENTIFIER) { + printLog("Not implemented"); + exit(0); + } + AstTreeIdentifier *function_metadata = function->metadata; + CodeGeneratorCall *callMetadata = a404m_malloc(sizeof(*callMetadata)); + callMetadata->label_begin = function_metadata->name_begin; + callMetadata->label_end = function_metadata->name_end; + generateCodePushCode(codes, + createGenerateCode(label_begin, label_end, + CODE_GENERATOR_INSTRUCTION_CALL, + callMetadata)); + } goto OK; + case AST_TREE_TOKEN_IDENTIFIER: case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: @@ -98,9 +123,9 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, label_end = NULL; } - generateCodePushCode(codes, - createGenerateCode(label_begin, label_end, - CODE_GENERATOR_INSTRUCTION_RET)); + generateCodePushCode(codes, createGenerateCode(label_begin, label_end, + CODE_GENERATOR_INSTRUCTION_RET, + NULL)); return true; } @@ -154,6 +179,18 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) { strlen(INST)); } continue; + case CODE_GENERATOR_INSTRUCTION_CALL: { + CodeGeneratorCall *metadata = code.metadata; + constexpr char CALL_INST[] = "call "; + codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, + CALL_INST, strlen(CALL_INST)); + codeGeneratorAppendFlatASMCommand( + &fasm, &fasm_size, &fasm_inserted, metadata->label_begin, + metadata->label_end - metadata->label_begin); + codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, "\n", + 1); + } + continue; case CODE_GENERATOR_INSTRUCTION_RET: { constexpr char INST[] = "ret\n"; codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, INST, diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h index f9ac6c9..94552ed 100644 --- a/src/compiler/code-generator.h +++ b/src/compiler/code-generator.h @@ -6,6 +6,7 @@ typedef enum CodeGeneratorInstruction : uint8_t { CODE_GENERATOR_INSTRUCTION_PRINT, + CODE_GENERATOR_INSTRUCTION_CALL, CODE_GENERATOR_INSTRUCTION_RET, } CodeGeneratorInstruction; @@ -13,8 +14,14 @@ typedef struct CodeGeneratorCode { char *label_begin; char *label_end; CodeGeneratorInstruction instruction; + void *metadata; } CodeGeneratorCode; +typedef struct CodeGeneratorCall { + char *label_begin; + char *label_end; +} CodeGeneratorCall; + typedef struct CodeGeneratorCodes { CodeGeneratorCode *codes; size_t codes_size; @@ -23,7 +30,7 @@ typedef struct CodeGeneratorCodes { void codeGeneratorDelete(CodeGeneratorCodes *code); CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end, - CodeGeneratorInstruction instruction); + CodeGeneratorInstruction instruction,void *metadata); CodeGeneratorCode *newGenerateCode(char *label_begin, char *label_end, CodeGeneratorInstruction instruction); @@ -32,8 +39,9 @@ void generateCodePushCode(CodeGeneratorCodes *codes, CodeGeneratorCode code); CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot); -bool codeGeneratorAstTreeFunction(char *label_begin,char *label_end,AstTree astTree, CodeGeneratorCodes *codes); +bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end, + AstTree astTree, CodeGeneratorCodes *codes); char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes); -bool codeGeneratorFlatASMExec(const char *filePath,const char *fasm); +bool codeGeneratorFlatASMExec(const char *filePath, const char *fasm); diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 7ec9e1c..14125cc 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -26,24 +26,26 @@ const char *PARSER_TOKEN_STRINGS[] = { "PARSER_TOKEN_FUNCTION_DEFINITION", + "PARSER_TOKEN_FUNCTION_CALL", + "PARSER_TOKEN_NONE", }; static constexpr ParserOrder PARSER_ORDER[] = { { .ltr = true, - .size = 2, + .size = 1, .data = { - LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS, LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET, }, }, { .ltr = true, - .size = 2, + .size = 3, .data = { + LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS, LEXER_TOKEN_IDENTIFIER, LEXER_TOKEN_KEYWORD_VOID, }, @@ -183,6 +185,26 @@ void parserNodePrint(const ParserNode *node, int indent) { printf(" "); } goto RETURN_SUCCESS; + case PARSER_TOKEN_FUNCTION_CALL: { + const ParserNodeFunctionCall *metadata = node->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("function=\n"); + parserNodePrint(metadata->function, indent + 1); + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("params=[\n"); + for (size_t i = 0; i < metadata->params->size; ++i) { + parserNodePrint(metadata->params->data[i], indent + 1); + printf(",\n"); + } + printf("]\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + } + goto RETURN_SUCCESS; case PARSER_TOKEN_NONE: } printLog("Bad token '%d'", node->token); @@ -241,6 +263,17 @@ void parserNodeDelete(ParserNode *node) { free(metadata); } goto RETURN_SUCCESS; + case PARSER_TOKEN_FUNCTION_CALL: { + ParserNodeFunctionCall *metadata = node->metadata; + parserNodeDelete(metadata->function); + for (size_t i = 0; i < metadata->params->size; ++i) { + parserNodeDelete(metadata->params->data[i]); + } + free(metadata->params->data); + free(metadata->params); + free(metadata); + } + goto RETURN_SUCCESS; case PARSER_TOKEN_NONE: } @@ -381,24 +414,21 @@ ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent) { } ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) { - ParserNode *parserNode = newParserNode( - PARSER_TOKEN_IDENTIFIER, node->str_begin, node->str_end, NULL, parent); - node->parserNode = parserNode; - return parserNode; + return node->parserNode = + newParserNode(PARSER_TOKEN_IDENTIFIER, node->str_begin, + node->str_end, NULL, parent); } ParserNode *parserVoid(LexerNode *node, ParserNode *parent) { - ParserNode *parserNode = newParserNode( - PARSER_TOKEN_TYPE_VOID, node->str_begin, node->str_end, NULL, parent); - node->parserNode = parserNode; - return parserNode; + return node->parserNode = + newParserNode(PARSER_TOKEN_TYPE_VOID, node->str_begin, + node->str_end, NULL, parent); } ParserNode *parserPrint(LexerNode *node, ParserNode *parent) { - ParserNode *parserNode = newParserNode( - PARSER_TOKEN_KEYWORD_PRINT, node->str_begin, node->str_end, NULL, parent); - node->parserNode = parserNode; - return parserNode; + return node->parserNode = + newParserNode(PARSER_TOKEN_KEYWORD_PRINT, node->str_begin, + node->str_end, NULL, parent); } ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent) { @@ -461,17 +491,45 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin, return NULL; } - ParserNode *parserNode = - newParserNode(PARSER_TOKEN_SYMBOL_PARENTHESIS, opening->str_begin, - closing->str_end, NULL, parent); + LexerNode *beforeNode = opening - 1; + ParserNode *before; + if (beforeNode < begin || beforeNode->parserNode == NULL || + (before = getUntilCommonParent(beforeNode->parserNode, parent)) == NULL || + !isExpression(before)) { + before = NULL; + } - opening->parserNode = parserNode; - closing->parserNode = parserNode; - if (parserNodeArray(opening + 1, closing, parserNode)) { - return parserNode; + if (before == NULL) { + ParserNode *parserNode = + newParserNode(PARSER_TOKEN_SYMBOL_PARENTHESIS, opening->str_begin, + closing->str_end, NULL, parent); + + opening->parserNode = parserNode; + closing->parserNode = parserNode; + if (parserNodeArray(opening + 1, closing, parserNode)) { + return parserNode; + } else { + free(parserNode); + return NULL; + } } else { - free(parserNode); - return NULL; + ParserNode *parserNode = + newParserNode(PARSER_TOKEN_FUNCTION_CALL, before->str_begin, + closing->str_end, NULL, parent); + + before->parent = parserNode; + opening->parserNode = parserNode; + closing->parserNode = parserNode; + if (parserNodeArray(opening + 1, closing, parserNode)) { + ParserNodeFunctionCall *metadata = malloc(sizeof(*metadata)); + metadata->function = before; + metadata->params = parserNode->metadata; + parserNode->metadata = metadata; + return parserNode; + } else { + free(parserNode); + return NULL; + } } } @@ -683,6 +741,7 @@ bool isExpression(ParserNode *node) { case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_KEYWORD_PRINT: + case PARSER_TOKEN_FUNCTION_CALL: return true; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_TYPE_FUNCTION: @@ -711,6 +770,7 @@ bool isType(ParserNode *node) { case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: + case PARSER_TOKEN_FUNCTION_CALL: return false; case PARSER_TOKEN_NONE: } @@ -721,6 +781,7 @@ bool isType(ParserNode *node) { bool isValue(ParserNode *node) { switch (node->token) { case PARSER_TOKEN_FUNCTION_DEFINITION: + case PARSER_TOKEN_FUNCTION_CALL: return true; case PARSER_TOKEN_TYPE_VOID: case PARSER_TOKEN_IDENTIFIER: diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 7d98074..fb65358 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -22,6 +22,8 @@ typedef enum ParserToken { PARSER_TOKEN_FUNCTION_DEFINITION, + PARSER_TOKEN_FUNCTION_CALL, + PARSER_TOKEN_NONE, } ParserToken; @@ -63,9 +65,14 @@ typedef struct ParserNodeArray { size_t size; } ParserNodeArray; +typedef struct ParserNodeFunctionCall { + ParserNode *function; + ParserNodeArray *params; +} ParserNodeFunctionCall; + typedef ParserNode ParserNodeEOLMetadata; -void parserNodePrint(const ParserNode *node,int indent); +void parserNodePrint(const ParserNode *node, int indent); void parserNodeDelete(ParserNode *node); ParserNode *parser(LexerNodeArray lexed); -- cgit v1.2.3