summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/ast-tree.c191
-rw-r--r--src/compiler/ast-tree.h17
-rw-r--r--src/compiler/lexer.c7
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c107
-rw-r--r--src/compiler/parser.h5
6 files changed, 293 insertions, 35 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index f92b95c..aeb1391 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -222,12 +222,27 @@ void astTreePrint(const AstTree *tree, int indent) {
for (int i = 0; i < indent; ++i)
printf(" ");
printf("body=\n");
- astTreePrint(metadata->body, indent + 1);
+ astTreePrint(metadata->ifBody, indent + 1);
printf("\n");
for (int i = 0; i < indent; ++i)
printf(" ");
}
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_SCOPE: {
+ AstTreeScope *metadata = tree->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("expressions=[\n");
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ astTreePrint(metadata->expressions[i], indent + 1);
+ printf(",\n");
+ }
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("]");
+ }
+ goto RETURN_SUCCESS;
case AST_TREE_TOKEN_NONE:
}
@@ -332,10 +347,24 @@ void astTreeDestroy(AstTree tree) {
case AST_TREE_TOKEN_KEYWORD_IF: {
AstTreeIf *metadata = tree.metadata;
astTreeDelete(metadata->condition);
- astTreeDelete(metadata->body);
+ astTreeDelete(metadata->ifBody);
+ free(metadata);
+ }
+ return;
+ case AST_TREE_TOKEN_SCOPE: {
+ AstTreeScope *metadata = tree.metadata;
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ astTreeDelete(metadata->expressions[i]);
+ }
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ astTreeVariableDelete(metadata->variables.data[i]);
+ }
+ free(metadata->expressions);
+ free(metadata->variables.data);
free(metadata);
}
return;
+
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -793,9 +822,10 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
case PARSER_TOKEN_SYMBOL_EOL:
return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata,
helper);
+ case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
+ return astTreeParseCurlyBracket(parserNode, helper);
case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
- case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
case PARSER_TOKEN_NONE:
case PARSER_TOKEN_ROOT:
@@ -1216,19 +1246,135 @@ AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) {
return NULL;
}
- AstTree *body = astTreeParse(node_metadata->body, helper);
- if (body == NULL) {
+ AstTree *ifBody = astTreeParse(node_metadata->ifBody, helper);
+ if (ifBody == NULL) {
return NULL;
}
+ AstTree *elseBody;
+ if(node_metadata->elseBody != NULL){
+ elseBody = astTreeParse(node_metadata->elseBody, helper);
+ if(elseBody == NULL){
+ return NULL;
+ }
+ }else{
+ elseBody = NULL;
+ }
+
AstTreeIf *metadata = a404m_malloc(sizeof(*metadata));
metadata->condition = condition;
- metadata->body = body;
+ metadata->ifBody = ifBody;
+ metadata->elseBody = elseBody;
return newAstTree(AST_TREE_TOKEN_KEYWORD_IF, metadata, NULL,
parserNode->str_begin, parserNode->str_end);
}
+AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
+ AstTreeHelper *p_helper) {
+ ParserNodeArray *body = parserNode->metadata;
+
+ size_t expressions_size = 0;
+
+ AstTreeScope *scope = a404m_malloc(sizeof(*scope));
+ scope->variables.data = a404m_malloc(0);
+ scope->variables.size = 0;
+ scope->expressions = a404m_malloc(0);
+ scope->expressions_size = 0;
+
+ size_t variables_size = p_helper->variables_size + 1;
+ AstTreeVariables *variables[variables_size];
+ for (size_t i = 0; i < p_helper->variables_size; ++i) {
+ variables[i] = p_helper->variables[i];
+ }
+ variables[variables_size - 1] = &scope->variables;
+
+ AstTreeHelper helper = {
+ .variables = variables,
+ .variables_size = variables_size,
+ .variable = p_helper->variable,
+ .globalDeps = p_helper->globalDeps,
+ };
+
+ for (size_t i = 0; i < body->size; ++i) {
+ ParserNode *node = body->data[i];
+ switch (node->token) {
+ case PARSER_TOKEN_SYMBOL_EOL:
+ node = (ParserNodeSingleChildMetadata *)node->metadata;
+ goto OK_NODE;
+ case PARSER_TOKEN_KEYWORD_IF:
+ goto OK_NODE;
+ case PARSER_TOKEN_ROOT:
+ case PARSER_TOKEN_IDENTIFIER:
+ case PARSER_TOKEN_VALUE_U64:
+ case PARSER_TOKEN_VALUE_BOOL:
+ case PARSER_TOKEN_TYPE_TYPE:
+ case PARSER_TOKEN_TYPE_FUNCTION:
+ case PARSER_TOKEN_TYPE_VOID:
+ case PARSER_TOKEN_TYPE_U64:
+ case PARSER_TOKEN_TYPE_BOOL:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
+ case PARSER_TOKEN_KEYWORD_RETURN:
+ case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
+ case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
+ case PARSER_TOKEN_SYMBOL_PARENTHESIS:
+ case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_OPERATOR_ASSIGN:
+ case PARSER_TOKEN_OPERATOR_PLUS:
+ case PARSER_TOKEN_OPERATOR_MINUS:
+ case PARSER_TOKEN_OPERATOR_SUM:
+ case PARSER_TOKEN_OPERATOR_SUB:
+ case PARSER_TOKEN_OPERATOR_MULTIPLY:
+ case PARSER_TOKEN_OPERATOR_DIVIDE:
+ case PARSER_TOKEN_OPERATOR_MODULO:
+ case PARSER_TOKEN_FUNCTION_DEFINITION:
+ case PARSER_TOKEN_FUNCTION_CALL:
+ printError(node->str_begin, node->str_end, "Unexpected %s",
+ PARSER_TOKEN_STRINGS[node->token]);
+ goto RETURN_ERROR;
+ case PARSER_TOKEN_NONE:
+ }
+ UNREACHABLE;
+ OK_NODE:
+
+ if (node->token == PARSER_TOKEN_CONSTANT) {
+ if (!astTreeParseConstant(node, &helper)) {
+ goto RETURN_ERROR;
+ }
+ } else {
+ AstTree *tree = astTreeParse(node, &helper);
+
+ if (tree == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ if (expressions_size == scope->expressions_size) {
+ expressions_size += expressions_size / 2 + 1;
+ scope->expressions = a404m_realloc(
+ scope->expressions, expressions_size * sizeof(*scope->expressions));
+ }
+ scope->expressions[scope->expressions_size] = tree;
+ scope->expressions_size += 1;
+ }
+ }
+
+ scope->expressions =
+ a404m_realloc(scope->expressions,
+ scope->expressions_size * sizeof(*scope->expressions));
+
+ return newAstTree(AST_TREE_TOKEN_SCOPE, scope, NULL, parserNode->str_begin,
+ parserNode->str_end);
+
+RETURN_ERROR:
+ for (size_t i = 0; i < scope->expressions_size; ++i) {
+ // astTreeDelete(scope->expressions[i]);
+ }
+ free(scope->variables.data);
+ free(scope->expressions);
+ return NULL;
+}
+
AstTreeFunction *getFunction(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_FUNCTION:
@@ -1262,6 +1408,7 @@ AstTreeFunction *getFunction(AstTree *value) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return NULL;
case AST_TREE_TOKEN_NONE:
}
@@ -1293,6 +1440,7 @@ bool isConst(AstTree *value) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return false;
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *metadata = value->metadata;
@@ -1361,6 +1509,7 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
case AST_TREE_TOKEN_KEYWORD_IF:
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1384,6 +1533,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_OPERATOR_MODULO:
case AST_TREE_TOKEN_OPERATOR_PLUS:
case AST_TREE_TOKEN_OPERATOR_MINUS:
+ case AST_TREE_TOKEN_SCOPE:
return false;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1424,6 +1574,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
AstTree *tree) {
switch (tree->token) {
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1543,7 +1694,10 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) {
return setTypesVariableDefine(tree);
case AST_TREE_TOKEN_KEYWORD_IF:
return setTypesIf(tree, function);
+ case AST_TREE_TOKEN_SCOPE:
+ return setTypesScope(tree, function);
case AST_TREE_TOKEN_NONE:
+ break;
}
UNREACHABLE;
}
@@ -1733,7 +1887,7 @@ bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
AstTreeIf *metadata = tree->metadata;
if (!setAllTypes(metadata->condition, function) ||
- !setAllTypes(metadata->body, function)) {
+ !setAllTypes(metadata->ifBody, function)) {
return false;
}
@@ -1748,6 +1902,26 @@ bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
return true;
}
+bool setTypesScope(AstTree *tree, AstTreeFunction *function) {
+ AstTreeScope *metadata = tree->metadata;
+
+ tree->type = &AST_TREE_VOID_TYPE;
+
+ for (size_t i = 0; i < metadata->expressions_size; ++i) {
+ if (!setAllTypes(metadata->expressions[i], function)) {
+ return false;
+ }
+ }
+
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ if (!setTypesAstVariable(metadata->variables.data[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool setTypesAstInfix(AstTreeInfix *infix) {
return setAllTypes(&infix->left, NULL) && setAllTypes(&infix->right, NULL);
}
@@ -1787,8 +1961,10 @@ bool astTreeClean(AstTree *tree) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
return true;
case AST_TREE_TOKEN_NONE:
+ break;
}
UNREACHABLE;
}
@@ -1879,6 +2055,7 @@ size_t astTreeTypeSize(AstTree tree) {
case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
case AST_TREE_TOKEN_OPERATOR_DIVIDE:
case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 38a6f66..594b213 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -33,6 +33,8 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_OPERATOR_DIVIDE,
AST_TREE_TOKEN_OPERATOR_MODULO,
+ AST_TREE_TOKEN_SCOPE,
+
AST_TREE_TOKEN_NONE,
} AstTreeToken;
@@ -109,7 +111,8 @@ typedef struct AstTreeReturn {
typedef struct AstTreeIf {
AstTree *condition;
- AstTree *body;
+ AstTree *ifBody;
+ AstTree *elseBody;
} AstTreeIf;
typedef struct AstTreeHelper {
@@ -141,31 +144,22 @@ AstTreeVariable *getVariable(AstTreeHelper *helper, char *name_begin,
char *name_end);
AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseTypeFunction(ParserNode *parserNode,
AstTreeHelper *helper);
-
AstTree *astTreeParseFunctionCall(ParserNode *parserNode,
AstTreeHelper *helper);
-
AstTree *astTreeParseIdentifier(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParsePrintU64(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseReturn(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseBinaryOperator(ParserNode *parserNode,
AstTreeHelper *helper, AstTreeToken token);
-
AstTree *astTreeParseUnaryOperator(ParserNode *parserNode,
AstTreeHelper *helper, AstTreeToken token);
-
bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper);
-
AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTreeHelper *helper);
AstTreeFunction *getFunction(AstTree *value);
bool isConst(AstTree *value);
@@ -188,6 +182,7 @@ bool setTypesOperatorInfix(AstTree *tree);
bool setTypesOperatorUnary(AstTree *tree);
bool setTypesVariableDefine(AstTree *tree);
bool setTypesIf(AstTree *tree,AstTreeFunction *function);
+bool setTypesScope(AstTree *tree,AstTreeFunction *function);
bool setTypesAstVariable(AstTreeVariable *variable);
bool setTypesAstInfix(AstTreeInfix *infix);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index a61c3af..1f45be0 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -21,6 +21,7 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_KEYWORD_TRUE",
"LEXER_TOKEN_KEYWORD_FALSE",
"LEXER_TOKEN_KEYWORD_IF",
+ "LEXER_TOKEN_KEYWORD_ELSE",
"LEXER_TOKEN_NUMBER",
@@ -68,14 +69,15 @@ const size_t LEXER_SYMBOL_SIZE =
sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
const char *LEXER_KEYWORD_STRINGS[] = {
- "type", "void", "u64", "bool", "print_u64", "return", "true", "false", "if",
+ "type", "void", "u64", "bool", "print_u64",
+ "return", "true", "false", "if", "else",
};
const LexerToken LEXER_KEYWORD_TOKENS[] = {
LEXER_TOKEN_KEYWORD_TYPE, LEXER_TOKEN_KEYWORD_VOID,
LEXER_TOKEN_KEYWORD_U64, LEXER_TOKEN_KEYWORD_BOOL,
LEXER_TOKEN_KEYWORD_PRINT_U64, LEXER_TOKEN_KEYWORD_RETURN,
LEXER_TOKEN_KEYWORD_TRUE, LEXER_TOKEN_KEYWORD_FALSE,
- LEXER_TOKEN_KEYWORD_IF,
+ LEXER_TOKEN_KEYWORD_IF, LEXER_TOKEN_KEYWORD_ELSE,
};
const size_t LEXER_KEYWORD_SIZE =
sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
@@ -208,6 +210,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_KEYWORD_TRUE:
case LEXER_TOKEN_KEYWORD_FALSE:
case LEXER_TOKEN_KEYWORD_IF:
+ case LEXER_TOKEN_KEYWORD_ELSE:
case LEXER_TOKEN_NUMBER:
case LEXER_TOKEN_SYMBOL_EOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 4e74d1d..e7afd62 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -14,6 +14,7 @@ typedef enum LexerToken {
LEXER_TOKEN_KEYWORD_TRUE,
LEXER_TOKEN_KEYWORD_FALSE,
LEXER_TOKEN_KEYWORD_IF,
+ LEXER_TOKEN_KEYWORD_ELSE,
LEXER_TOKEN_NUMBER,
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) {
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index cb90b71..60825a9 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -106,7 +106,8 @@ typedef bool ParserNodeBoolMetadata;
typedef struct ParserNodeIfMetadata {
ParserNode *condition;
- ParserNode *body;
+ ParserNode *ifBody;
+ ParserNode *elseBody;
}ParserNodeIfMetadata;
void parserNodePrint(const ParserNode *node, int indent);
@@ -122,7 +123,9 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *parent, bool *conti);
ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent);
+ParserNode *getUntilCommonParents(ParserNode *node, ParserNode *parent,ParserNode *parent2);
ParserNode *getNextUsingCommonParent(LexerNode *node,LexerNode *end, ParserNode *parent);
+LexerNode *getNextLexerNodeUsingCommonParent(LexerNode *node,LexerNode *end, ParserNode *parent);
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent);
ParserNode *parserType(LexerNode *node, ParserNode *parent);