summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-02-12 11:55:38 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-02-12 11:55:38 +0330
commit5c336962d3d0a885a870708076f154ee422fee12 (patch)
tree6f24bf2de914d94fd309d34c7c82e8025692154b /src/compiler
parent217b2c70adfd60756591dd6b06b60279f805a596 (diff)
add if
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/ast-tree.c131
-rw-r--r--src/compiler/ast-tree.h17
-rw-r--r--src/compiler/lexer.c5
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c125
-rw-r--r--src/compiler/parser.h9
6 files changed, 269 insertions, 19 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 4976750..f92b95c 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -211,7 +211,23 @@ void astTreePrint(const AstTree *tree, int indent) {
printf(" ");
}
goto RETURN_SUCCESS;
-
+ case AST_TREE_TOKEN_KEYWORD_IF: {
+ AstTreeIf *metadata = tree->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("condition=\n");
+ astTreePrint(metadata->condition, indent + 1);
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("body=\n");
+ astTreePrint(metadata->body, indent + 1);
+ printf("\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ }
+ goto RETURN_SUCCESS;
case AST_TREE_TOKEN_NONE:
}
@@ -313,6 +329,13 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
+ case AST_TREE_TOKEN_KEYWORD_IF: {
+ AstTreeIf *metadata = tree.metadata;
+ astTreeDelete(metadata->condition);
+ astTreeDelete(metadata->body);
+ free(metadata);
+ }
+ return;
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -582,6 +605,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_OPERATOR_DIVIDE:
case PARSER_TOKEN_OPERATOR_MODULO:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
+ case PARSER_TOKEN_KEYWORD_IF:
goto AFTER_SWITCH;
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_TYPE_TYPE:
@@ -764,8 +788,12 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
AST_TREE_TOKEN_OPERATOR_MINUS);
case PARSER_TOKEN_VARIABLE:
return astTreeParseVariable(parserNode, helper);
- case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_KEYWORD_IF:
+ return astTreeParseIf(parserNode, helper);
case PARSER_TOKEN_SYMBOL_EOL:
+ return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata,
+ helper);
+ case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
@@ -848,13 +876,46 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) {
}
for (size_t i = 0; i < body->size; ++i) {
- ParserNode *eol = body->data[i];
- if (eol->token != PARSER_TOKEN_SYMBOL_EOL) {
- printError(eol->str_begin, eol->str_end, "Unexpected %s",
- PARSER_TOKEN_STRINGS[eol->token]);
+ 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:
}
- ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
+ UNREACHABLE;
+ OK_NODE:
if (node->token == PARSER_TOKEN_CONSTANT) {
if (!astTreeParseConstant(node, &helper)) {
@@ -1147,15 +1208,31 @@ RETURN_ERROR:
return NULL;
}
+AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) {
+ ParserNodeIfMetadata *node_metadata = parserNode->metadata;
+
+ AstTree *condition = astTreeParse(node_metadata->condition, helper);
+ if (condition == NULL) {
+ return NULL;
+ }
+
+ AstTree *body = astTreeParse(node_metadata->body, helper);
+ if (body == NULL) {
+ return NULL;
+ }
+
+ AstTreeIf *metadata = a404m_malloc(sizeof(*metadata));
+ metadata->condition = condition;
+ metadata->body = body;
+
+ return newAstTree(AST_TREE_TOKEN_KEYWORD_IF, metadata, NULL,
+ parserNode->str_begin, parserNode->str_end);
+}
+
AstTreeFunction *getFunction(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_FUNCTION:
return value->metadata;
- case AST_TREE_TOKEN_FUNCTION_CALL: {
- AstTreeFunctionCall *metadata = value->metadata;
- AstTreeFunction *function = metadata->function->metadata;
- return getFunction(function->returnType);
- }
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *metadata = value->metadata;
if (metadata->value->token == AST_TREE_TOKEN_FUNCTION) {
@@ -1164,8 +1241,10 @@ AstTreeFunction *getFunction(AstTree *value) {
return NULL;
}
}
+ case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1203,6 +1282,7 @@ bool isConst(AstTree *value) {
return true;
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_OPERATOR_ASSIGN:
@@ -1280,6 +1360,7 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1290,6 +1371,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_U64:
case AST_TREE_TOKEN_VALUE_BOOL:
@@ -1392,10 +1474,11 @@ bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
case AST_TREE_TOKEN_FUNCTION: {
return false;
}
- case AST_TREE_TOKEN_NONE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ case AST_TREE_TOKEN_KEYWORD_IF:
+ case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
}
@@ -1458,6 +1541,8 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) {
return setTypesOperatorInfix(tree);
case AST_TREE_TOKEN_VARIABLE_DEFINE:
return setTypesVariableDefine(tree);
+ case AST_TREE_TOKEN_KEYWORD_IF:
+ return setTypesIf(tree, function);
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1644,6 +1729,25 @@ bool setTypesAstVariable(AstTreeVariable *variable) {
return true;
}
+bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
+ AstTreeIf *metadata = tree->metadata;
+
+ if (!setAllTypes(metadata->condition, function) ||
+ !setAllTypes(metadata->body, function)) {
+ return false;
+ }
+
+ if (!typeIsEqual(metadata->condition->type, &AST_TREE_BOOL_TYPE)) {
+ printError(metadata->condition->str_begin, metadata->condition->str_end,
+ "If condition must be boolean");
+ return false;
+ }
+
+ tree->type = &AST_TREE_VOID_TYPE;
+
+ return true;
+}
+
bool setTypesAstInfix(AstTreeInfix *infix) {
return setAllTypes(&infix->left, NULL) && setAllTypes(&infix->right, NULL);
}
@@ -1664,6 +1768,7 @@ bool astTreeClean(AstTree *tree) {
return astTreeCleanFunction(tree);
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 579d919..38a6f66 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -9,6 +9,7 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_KEYWORD_PRINT_U64,
AST_TREE_TOKEN_KEYWORD_RETURN,
+ AST_TREE_TOKEN_KEYWORD_IF,
AST_TREE_TOKEN_TYPE_TYPE,
AST_TREE_TOKEN_TYPE_FUNCTION,
@@ -106,6 +107,11 @@ typedef struct AstTreeReturn {
AstTree *value;
} AstTreeReturn;
+typedef struct AstTreeIf {
+ AstTree *condition;
+ AstTree *body;
+} AstTreeIf;
+
typedef struct AstTreeHelper {
AstTreeVariables **variables;
size_t variables_size;
@@ -129,7 +135,8 @@ AstTreeVariables copyAstTreeVariables(AstTreeVariables variables);
AstTreeRoot *makeAstTree(ParserNode *parsedRoot);
-bool pushVariable(AstTreeHelper *helper,AstTreeVariables *variables, AstTreeVariable *variable);
+bool pushVariable(AstTreeHelper *helper, AstTreeVariables *variables,
+ AstTreeVariable *variable);
AstTreeVariable *getVariable(AstTreeHelper *helper, char *name_begin,
char *name_end);
@@ -158,14 +165,17 @@ bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper);
+
AstTreeFunction *getFunction(AstTree *value);
bool isConst(AstTree *value);
AstTree *makeTypeOf(AstTree *value);
bool typeIsEqual(const AstTree *type0, const AstTree *type1);
-bool isCircularDependencies(AstTreeHelper *helper,AstTreeVariable *variable,AstTree *tree);
+bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
+ AstTree *tree);
-bool setAllTypesRoot(AstTreeRoot *root,AstTreeHelper *helper);
+bool setAllTypesRoot(AstTreeRoot *root, AstTreeHelper *helper);
bool setAllTypes(AstTree *tree, AstTreeFunction *function);
bool setTypesFunction(AstTree *tree);
bool setTypesPrintU64(AstTree *tree);
@@ -177,6 +187,7 @@ bool setTypesOperatorAssign(AstTree *tree);
bool setTypesOperatorInfix(AstTree *tree);
bool setTypesOperatorUnary(AstTree *tree);
bool setTypesVariableDefine(AstTree *tree);
+bool setTypesIf(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 baedf24..a61c3af 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -20,6 +20,7 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_KEYWORD_RETURN",
"LEXER_TOKEN_KEYWORD_TRUE",
"LEXER_TOKEN_KEYWORD_FALSE",
+ "LEXER_TOKEN_KEYWORD_IF",
"LEXER_TOKEN_NUMBER",
@@ -67,13 +68,14 @@ 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",
+ "type", "void", "u64", "bool", "print_u64", "return", "true", "false", "if",
};
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,
};
const size_t LEXER_KEYWORD_SIZE =
sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
@@ -205,6 +207,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_KEYWORD_RETURN:
case LEXER_TOKEN_KEYWORD_TRUE:
case LEXER_TOKEN_KEYWORD_FALSE:
+ case LEXER_TOKEN_KEYWORD_IF:
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 bc38270..4e74d1d 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -13,6 +13,7 @@ typedef enum LexerToken {
LEXER_TOKEN_KEYWORD_RETURN,
LEXER_TOKEN_KEYWORD_TRUE,
LEXER_TOKEN_KEYWORD_FALSE,
+ LEXER_TOKEN_KEYWORD_IF,
LEXER_TOKEN_NUMBER,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index 9cdf141..d4364af 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -25,6 +25,7 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_KEYWORD_PRINT_U64",
"PARSER_TOKEN_KEYWORD_RETURN",
+ "PARSER_TOKEN_KEYWORD_IF",
"PARSER_TOKEN_CONSTANT",
"PARSER_TOKEN_VARIABLE",
@@ -101,6 +102,10 @@ static constexpr ParserOrder PARSER_ORDER[] = {
.ltr = true,
ORDER_ARRAY(LEXER_TOKEN_SYMBOL_EOL, LEXER_TOKEN_SYMBOL_COMMA, ),
},
+ {
+ .ltr = true,
+ ORDER_ARRAY(LEXER_TOKEN_KEYWORD_IF, ),
+ },
};
static constexpr size_t PARSER_ORDER_SIZE =
@@ -282,6 +287,24 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(" ");
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_KEYWORD_IF: {
+ ParserNodeIfMetadata *metadata = node->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("condition=\n");
+ parserNodePrint(metadata->condition, indent + 1);
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("body=\n");
+ parserNodePrint(metadata->body, indent + 1);
+ printf("\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ free(metadata);
+ }
+ goto RETURN_SUCCESS;
case PARSER_TOKEN_NONE:
}
UNREACHABLE;
@@ -378,6 +401,13 @@ void parserNodeDelete(ParserNode *node) {
free(metadata);
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_KEYWORD_IF: {
+ ParserNodeIfMetadata *metadata = node->metadata;
+ parserNodeDelete(metadata->condition);
+ parserNodeDelete(metadata->body);
+ free(metadata);
+ }
+ goto RETURN_SUCCESS;
case PARSER_TOKEN_NONE:
}
UNREACHABLE;
@@ -545,6 +575,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
*conti = result == NULL;
return result;
}
+ case LEXER_TOKEN_KEYWORD_IF:
+ return parserIf(node, end, parent);
case LEXER_TOKEN_SYMBOL:
case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET:
@@ -555,12 +587,35 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
}
ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent) {
- while (node != NULL && node->parent != parent) {
+ while (node != NULL && node != parent && node->parent != parent) {
node = node->parent;
}
return node;
}
+ParserNode *getNextUsingCommonParent(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 getUntilCommonParent(node->parserNode, parent);
+ }
+ }
+
+ return NULL;
+}
+
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) {
return node->parserNode =
newParserNode(PARSER_TOKEN_IDENTIFIER, node->str_begin,
@@ -854,12 +909,43 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
}
ParserNodeArray *bodyArray = body->metadata;
for (size_t i = 0; i < bodyArray->size; ++i) {
- if (bodyArray->data[i]->token != PARSER_TOKEN_SYMBOL_EOL) {
+ switch (bodyArray->data[i]->token) {
+ case PARSER_TOKEN_SYMBOL_EOL:
+ case PARSER_TOKEN_KEYWORD_IF:
+ continue;
+ 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(bodyArray->data[i]->str_begin, bodyArray->data[i]->str_end,
"Maybe forgot a ; with %s",
PARSER_TOKEN_STRINGS[bodyArray->data[i]->token]);
return NULL;
+ case PARSER_TOKEN_NONE:
}
+ UNREACHABLE;
}
}
@@ -1054,6 +1140,38 @@ ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin,
(ParserNodeSingleChildMetadata *)right, parent);
}
+ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) {
+ LexerNode *conditionNode = node + 1;
+ if (conditionNode >= end) {
+ printError(node->str_begin, node->str_end, "If has no condition");
+ return NULL;
+ }
+
+ ParserNode *condition =
+ getUntilCommonParent(conditionNode->parserNode, parent);
+
+ if (condition == NULL) {
+ printError(conditionNode->str_begin, conditionNode->str_end,
+ "If has bad condition");
+ return NULL;
+ }
+
+ ParserNode *body = getNextUsingCommonParent(conditionNode, end, parent);
+
+ if (body == NULL) {
+ printError(node->str_begin, node->str_end, "If has bad body");
+ return NULL;
+ }
+
+ ParserNodeIfMetadata *metadata = a404m_malloc(sizeof(*metadata));
+ metadata->condition = condition;
+ metadata->body = body;
+
+ return condition->parent = body->parent = node->parserNode =
+ newParserNode(PARSER_TOKEN_KEYWORD_IF, node->str_begin,
+ node->str_end, metadata, parent);
+}
+
bool isAllArguments(const ParserNodeArray *nodes) {
for (size_t i = 0; i < nodes->size; ++i) {
const ParserNode *node = nodes->data[i];
@@ -1084,6 +1202,7 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_OPERATOR_MODULO:
case PARSER_TOKEN_VALUE_U64:
case PARSER_TOKEN_VALUE_BOOL:
+ case PARSER_TOKEN_KEYWORD_IF:
return true;
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_TYPE_TYPE:
@@ -1130,6 +1249,7 @@ bool isType(ParserNode *node) {
case PARSER_TOKEN_OPERATOR_MULTIPLY:
case PARSER_TOKEN_OPERATOR_DIVIDE:
case PARSER_TOKEN_OPERATOR_MODULO:
+ case PARSER_TOKEN_KEYWORD_IF:
return false;
case PARSER_TOKEN_NONE:
}
@@ -1155,6 +1275,7 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_TYPE_U64:
case PARSER_TOKEN_TYPE_BOOL:
+ case PARSER_TOKEN_KEYWORD_IF:
return true;
case PARSER_TOKEN_TYPE_FUNCTION:
case PARSER_TOKEN_CONSTANT:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 2d57538..cb90b71 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -20,6 +20,7 @@ typedef enum ParserToken {
PARSER_TOKEN_KEYWORD_PRINT_U64,
PARSER_TOKEN_KEYWORD_RETURN,
+ PARSER_TOKEN_KEYWORD_IF,
PARSER_TOKEN_CONSTANT,
PARSER_TOKEN_VARIABLE,
@@ -103,6 +104,11 @@ typedef struct ParserNodeReturnMetadata {
typedef bool ParserNodeBoolMetadata;
+typedef struct ParserNodeIfMetadata {
+ ParserNode *condition;
+ ParserNode *body;
+}ParserNodeIfMetadata;
+
void parserNodePrint(const ParserNode *node, int indent);
void parserNodeDelete(ParserNode *node);
@@ -116,6 +122,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
ParserNode *parent, bool *conti);
ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent);
+ParserNode *getNextUsingCommonParent(LexerNode *node,LexerNode *end, ParserNode *parent);
ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent);
ParserNode *parserType(LexerNode *node, ParserNode *parent);
@@ -143,6 +150,8 @@ ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin,
LexerNode *end, ParserNode *parent,
ParserToken token,
LexerToken laterToken);
+ParserNode *parserIf(LexerNode *node, LexerNode *end,
+ ParserNode *parent);
bool isAllArguments(const ParserNodeArray *nodes);