From 188fc08d3b3095a843c24207fe3a73999b2894fb Mon Sep 17 00:00:00 2001 From: A404M Date: Wed, 12 Feb 2025 16:58:21 +0330 Subject: enhanced if with else fix if scope bug --- src/compiler/parser.c | 107 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 14 deletions(-) (limited to 'src/compiler/parser.c') diff --git a/src/compiler/parser.c b/src/compiler/parser.c index d4364af..b952dc1 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -297,8 +297,13 @@ void parserNodePrint(const ParserNode *node, int indent) { printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); - printf("body=\n"); - parserNodePrint(metadata->body, indent + 1); + printf("ifBody=\n"); + parserNodePrint(metadata->ifBody, indent + 1); + printf("\n,"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("elseBody=\n"); + parserNodePrint(metadata->elseBody, indent + 1); printf("\n"); for (int i = 0; i < indent; ++i) printf(" "); @@ -404,7 +409,8 @@ void parserNodeDelete(ParserNode *node) { case PARSER_TOKEN_KEYWORD_IF: { ParserNodeIfMetadata *metadata = node->metadata; parserNodeDelete(metadata->condition); - parserNodeDelete(metadata->body); + parserNodeDelete(metadata->ifBody); + parserNodeDelete(metadata->elseBody); free(metadata); } goto RETURN_SUCCESS; @@ -577,6 +583,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, } case LEXER_TOKEN_KEYWORD_IF: return parserIf(node, end, parent); + case LEXER_TOKEN_KEYWORD_ELSE: case LEXER_TOKEN_SYMBOL: case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS: case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET: @@ -588,6 +595,23 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end, ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent) { while (node != NULL && node != parent && node->parent != parent) { + if (node == node->parent) { + return NULL; + } + + node = node->parent; + } + return node; +} + +ParserNode *getUntilCommonParents(ParserNode *node, ParserNode *parent, + ParserNode *parent2) { + while (node != NULL && node != parent && node->parent != parent && + node->parent != parent2) { + if (node == node->parent) { + return NULL; + } + node = node->parent; } return node; @@ -616,6 +640,29 @@ ParserNode *getNextUsingCommonParent(LexerNode *node, LexerNode *end, return NULL; } +LexerNode *getNextLexerNodeUsingCommonParent(LexerNode *node, LexerNode *end, + ParserNode *parent) { + ParserNode *parsed = getUntilCommonParent(node->parserNode, parent); + if (parsed == NULL) { + return NULL; + } + + while (true) { + node += 1; + if (node >= end) { + return NULL; + } + + ParserNode *newParsed = getUntilCommonParent(node->parserNode, parsed); + + if (newParsed == NULL) { + return node; + } + } + + return NULL; +} + ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) { return node->parserNode = newParserNode(PARSER_TOKEN_IDENTIFIER, node->str_begin, @@ -781,9 +828,11 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin, for (LexerNode *iter = closing - 1; iter >= begin; --iter) { if (iter->parserNode != NULL) { - ParserNode *pNode = getUntilCommonParent(iter->parserNode, parent); + ParserNode *pNode = + getUntilCommonParents(iter->parserNode, parent, parserNode); if (pNode == NULL) { printLog("Bad node", pNode->str_begin, pNode->str_end); + return NULL; } else { pNode->parent = parserNode; } @@ -850,9 +899,11 @@ ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin, for (LexerNode *iter = closing - 1; iter >= begin; --iter) { if (iter->parserNode != NULL) { - ParserNode *pNode = getUntilCommonParent(iter->parserNode, parent); + ParserNode *pNode = + getUntilCommonParents(iter->parserNode, parent, parserNode); if (pNode == NULL) { - printLog("Bad node", pNode->str_begin, pNode->str_end); + printLog(iter->str_begin, iter->str_end, "Bad node"); + return NULL; } else { pNode->parent = parserNode; } @@ -868,11 +919,11 @@ ParserNode *parserCurlyBrackets(LexerNode *closing, LexerNode *begin, return NULL; } - parserNode->str_begin = opening->str_begin, + parserNode->str_begin = opening->str_begin; parserNode->str_end = closing->str_end; - opening->parserNode = parserNode; - closing->parserNode = parserNode; + opening->parserNode = closing->parserNode = parserNode; + if (parserNodeArray(opening + 1, closing, parserNode)) { return parserNode; } else { @@ -1156,7 +1207,9 @@ ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) { return NULL; } - ParserNode *body = getNextUsingCommonParent(conditionNode, end, parent); + LexerNode *bodyNode = + getNextLexerNodeUsingCommonParent(conditionNode, end, parent); + ParserNode *body = getUntilCommonParent(bodyNode->parserNode, parent); if (body == NULL) { printError(node->str_begin, node->str_end, "If has bad body"); @@ -1165,11 +1218,37 @@ ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) { ParserNodeIfMetadata *metadata = a404m_malloc(sizeof(*metadata)); metadata->condition = condition; - metadata->body = body; + metadata->ifBody = body; + + LexerNode *elseNode = + getNextLexerNodeUsingCommonParent(bodyNode, end, parent); + if (elseNode == NULL || elseNode->token != LEXER_TOKEN_KEYWORD_ELSE) { + metadata->elseBody = NULL; + return condition->parent = body->parent = node->parserNode = + newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin, + body->str_end, metadata, parent); + } + + LexerNode *elseBodyNode = elseNode + 1; + + if (elseBodyNode >= end || elseBodyNode->parserNode == NULL) { + printError(elseNode->str_begin, elseNode->str_end, "Else has bad body"); + return NULL; + } + + ParserNode *elseBody = getUntilCommonParent(elseBodyNode->parserNode, parent); + + if (elseBody == NULL) { + printError(elseNode->str_begin, elseNode->str_end, "Else has bad body"); + return NULL; + } + + metadata->elseBody = elseBody; - return condition->parent = body->parent = node->parserNode = - newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin, - node->str_end, metadata, parent); + return elseBody->parent = elseNode->parserNode = condition->parent = + body->parent = node->parserNode = + newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin, + elseBody->str_end, metadata, parent); } bool isAllArguments(const ParserNodeArray *nodes) { -- cgit v1.2.3