From 302cc65d3e59937742c18475d63e22c482176fa7 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Mon, 10 Feb 2025 00:17:29 +0330
Subject: add - * / %

---
 src/compiler/ast-tree.c | 114 +++++++++++++++++++++++++++++++-----------------
 src/compiler/ast-tree.h |  13 +++---
 src/compiler/lexer.c    |  17 +++++++-
 src/compiler/lexer.h    |   4 ++
 src/compiler/parser.c   |  94 ++++++++++++++++++++++++++++-----------
 src/compiler/parser.h   |  13 ++++--
 6 files changed, 180 insertions(+), 75 deletions(-)

(limited to 'src/compiler')

diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index ea5da0b..d7769bc 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -58,6 +58,10 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
 
     "AST_TREE_TOKEN_OPERATOR_ASSIGN",
     "AST_TREE_TOKEN_OPERATOR_SUM",
+    "AST_TREE_TOKEN_OPERATOR_SUB",
+    "AST_TREE_TOKEN_OPERATOR_MULTIPLY",
+    "AST_TREE_TOKEN_OPERATOR_DIVIDE",
+    "AST_TREE_TOKEN_OPERATOR_MODULO",
 
     "AST_TREE_TOKEN_NONE",
 };
@@ -184,6 +188,10 @@ void astTreePrint(const AstTree *tree, int indent) {
   }
     goto RETURN_SUCCESS;
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN: {
     AstTreeInfix *metadata = tree->metadata;
     printf(",\n");
@@ -290,6 +298,10 @@ void astTreeDestroy(AstTree tree) {
   }
     return;
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN: {
     AstTreeInfix *metadata = tree.metadata;
     astTreeDestroy(metadata->left);
@@ -374,7 +386,11 @@ AstTree *copyAstTree(AstTree *tree) {
                       tree->str_begin, tree->str_end);
   }
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
-  case AST_TREE_TOKEN_OPERATOR_SUM: {
+  case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO: {
     AstTreeInfix *metadata = tree->metadata;
     AstTreeInfix *new_metadata = a404m_malloc(sizeof(*new_metadata));
     AstTree *left = copyAstTree(&metadata->left);
@@ -487,7 +503,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
   for (size_t i = 0; i < nodes->size; ++i) {
     ParserNode *eol = nodes->data[i];
     if (eol->token != PARSER_TOKEN_SYMBOL_EOL) {
-      printError(eol->str_begin, eol->str_end, "Unexpected %s",
+      printError(eol->str_begin, eol->str_end, "Did you forgot semicolon?",
                  PARSER_TOKEN_STRINGS[eol->token]);
       goto RETURN_ERROR;
     }
@@ -536,6 +552,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
     case PARSER_TOKEN_VALUE_BOOL:
     case PARSER_TOKEN_VALUE_U64:
     case PARSER_TOKEN_FUNCTION_DEFINITION:
+    case PARSER_TOKEN_FUNCTION_CALL:
       goto AFTER_SWITCH;
     case PARSER_TOKEN_ROOT:
     case PARSER_TOKEN_IDENTIFIER:
@@ -552,9 +569,12 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
     case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
     case PARSER_TOKEN_SYMBOL_PARENTHESIS:
     case PARSER_TOKEN_SYMBOL_COMMA:
-    case PARSER_TOKEN_FUNCTION_CALL:
     case PARSER_TOKEN_OPERATOR_ASSIGN:
     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:
       printError(node->str_begin, node->str_end, "Should not be here");
       goto RETURN_ERROR;
     case PARSER_TOKEN_NONE:
@@ -675,9 +695,23 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
   case PARSER_TOKEN_KEYWORD_RETURN:
     return astTreeParseReturn(parserNode, variables, variables_size);
   case PARSER_TOKEN_OPERATOR_ASSIGN:
-    return astTreeParseAssign(parserNode, variables, variables_size);
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_ASSIGN);
   case PARSER_TOKEN_OPERATOR_SUM:
-    return astTreeParseSum(parserNode, variables, variables_size);
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_SUM);
+  case PARSER_TOKEN_OPERATOR_SUB:
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_SUB);
+  case PARSER_TOKEN_OPERATOR_MULTIPLY:
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_MULTIPLY);
+  case PARSER_TOKEN_OPERATOR_DIVIDE:
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_DIVIDE);
+  case PARSER_TOKEN_OPERATOR_MODULO:
+    return astTreeParseBinaryOperator(parserNode, variables, variables_size,
+                                      AST_TREE_TOKEN_OPERATOR_MODULO);
   case PARSER_TOKEN_VARIABLE:
     return astTreeParseVariable(parserNode, variables, variables_size);
   case PARSER_TOKEN_CONSTANT:
@@ -944,35 +978,9 @@ AstTree *astTreeParseReturn(ParserNode *parserNode,
                     parserNode->str_begin, parserNode->str_end);
 }
 
-AstTree *astTreeParseAssign(ParserNode *parserNode,
-                            AstTreeVariables **variables,
-                            size_t variables_size) {
-  ParserNodeInfixMetadata *node_metadata = parserNode->metadata;
-
-  AstTree *left = astTreeParse(node_metadata->left, variables, variables_size);
-  if (left == NULL) {
-    return NULL;
-  }
-  AstTree *right =
-      astTreeParse(node_metadata->right, variables, variables_size);
-  if (right == NULL) {
-    return NULL;
-  }
-
-  AstTreeInfix *metadata = a404m_malloc(sizeof(*metadata));
-
-  metadata->left = *left;
-  metadata->right = *right;
-
-  free(left);
-  free(right);
-
-  return newAstTree(AST_TREE_TOKEN_OPERATOR_ASSIGN, metadata, NULL,
-                    parserNode->str_begin, parserNode->str_end);
-}
-
-AstTree *astTreeParseSum(ParserNode *parserNode, AstTreeVariables **variables,
-                         size_t variables_size) {
+AstTree *astTreeParseBinaryOperator(ParserNode *parserNode,
+                                    AstTreeVariables **variables,
+                                    size_t variables_size, AstTreeToken token) {
   ParserNodeInfixMetadata *node_metadata = parserNode->metadata;
 
   AstTree *left = astTreeParse(node_metadata->left, variables, variables_size);
@@ -993,8 +1001,8 @@ AstTree *astTreeParseSum(ParserNode *parserNode, AstTreeVariables **variables,
   free(left);
   free(right);
 
-  return newAstTree(AST_TREE_TOKEN_OPERATOR_SUM, metadata, NULL,
-                    parserNode->str_begin, parserNode->str_end);
+  return newAstTree(token, metadata, NULL, parserNode->str_begin,
+                    parserNode->str_end);
 }
 
 bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
@@ -1115,6 +1123,10 @@ AstTreeFunction *getFunction(AstTree *value) {
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
     return NULL;
   case AST_TREE_TOKEN_NONE:
   }
@@ -1139,6 +1151,10 @@ bool isConst(AstTree *value) {
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
     return false;
   case AST_TREE_TOKEN_VARIABLE: {
     AstTreeVariable *metadata = value->metadata;
@@ -1190,7 +1206,11 @@ AstTree *makeTypeOf(AstTree *value) {
     return copyAstTree(variable->type);
   }
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
-  case AST_TREE_TOKEN_OPERATOR_SUM: {
+  case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO: {
     AstTreeInfix *metadata = value->metadata;
     return copyAstTree(metadata->left.type);
   }
@@ -1213,6 +1233,10 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
     return false;
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
@@ -1289,7 +1313,11 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) {
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
     return setTypesOperatorAssign(tree);
   case AST_TREE_TOKEN_OPERATOR_SUM:
-    return setTypesOperatorSum(tree);
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
+    return setTypesOperatorInfix(tree);
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
     return setTypesVariableDefine(tree);
   case AST_TREE_TOKEN_NONE:
@@ -1429,7 +1457,7 @@ bool setTypesOperatorAssign(AstTree *tree) {
   }
 }
 
-bool setTypesOperatorSum(AstTree *tree) {
+bool setTypesOperatorInfix(AstTree *tree) {
   AstTreeInfix *infix = tree->metadata;
   if (!setTypesAstInfix(infix)) {
     return false;
@@ -1500,6 +1528,10 @@ bool astTreeClean(AstTree *tree) {
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
     return true;
   case AST_TREE_TOKEN_NONE:
   }
@@ -1586,6 +1618,10 @@ size_t astTreeTypeSize(AstTree tree) {
   case AST_TREE_TOKEN_VALUE_BOOL:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
   case AST_TREE_TOKEN_NONE:
   }
   UNREACHABLE;
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index d67560f..9caef63 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -25,6 +25,10 @@ typedef enum AstTreeToken {
 
   AST_TREE_TOKEN_OPERATOR_ASSIGN,
   AST_TREE_TOKEN_OPERATOR_SUM,
+  AST_TREE_TOKEN_OPERATOR_SUB,
+  AST_TREE_TOKEN_OPERATOR_MULTIPLY,
+  AST_TREE_TOKEN_OPERATOR_DIVIDE,
+  AST_TREE_TOKEN_OPERATOR_MODULO,
 
   AST_TREE_TOKEN_NONE,
 } AstTreeToken;
@@ -146,12 +150,9 @@ AstTree *astTreeParseReturn(ParserNode *parserNode,
                               AstTreeVariables **variables,
                               size_t variables_size);
 
-AstTree *astTreeParseAssign(ParserNode *parserNode,
+AstTree *astTreeParseBinaryOperator(ParserNode *parserNode,
                             AstTreeVariables **variables,
-                            size_t variables_size);
-
-AstTree *astTreeParseSum(ParserNode *parserNode, AstTreeVariables **variables,
-                         size_t variables_size);
+                            size_t variables_size,AstTreeToken token);
 
 bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
                           size_t variables_size);
@@ -174,7 +175,7 @@ bool setTypesTypeFunction(AstTree *tree);
 bool setTypesFunctionCall(AstTree *tree);
 bool setTypesVariable(AstTree *tree);
 bool setTypesOperatorAssign(AstTree *tree);
-bool setTypesOperatorSum(AstTree *tree);
+bool setTypesOperatorInfix(AstTree *tree);
 bool setTypesVariableDefine(AstTree *tree);
 
 bool setTypesAstVariable(AstTreeVariable *variable);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 52702ba..70cd1fb 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -33,12 +33,16 @@ const char *LEXER_TOKEN_STRINGS[] = {
     "LEXER_TOKEN_SYMBOL_ASSIGN",
     "LEXER_TOKEN_SYMBOL_COMMA",
     "LEXER_TOKEN_SYMBOL_PLUS",
+    "LEXER_TOKEN_SYMBOL_MINUS",
+    "LEXER_TOKEN_SYMBOL_MULTIPLY",
+    "LEXER_TOKEN_SYMBOL_DIVIDE",
+    "LEXER_TOKEN_SYMBOL_MODULO",
 
     "LEXER_TOKEN_NONE",
 };
 
 const char *LEXER_SYMBOL_STRINGS[] = {
-    ";", "(", ")", "{", "}", "->", ":", "=", ",", "+",
+    ";", "(", ")", "{", "}", "->", ":", "=", ",", "+", "-", "*", "/", "%",
 };
 const LexerToken LEXER_SYMBOL_TOKENS[] = {
     LEXER_TOKEN_SYMBOL_EOL,
@@ -51,6 +55,10 @@ const LexerToken LEXER_SYMBOL_TOKENS[] = {
     LEXER_TOKEN_SYMBOL_ASSIGN,
     LEXER_TOKEN_SYMBOL_COMMA,
     LEXER_TOKEN_SYMBOL_PLUS,
+    LEXER_TOKEN_SYMBOL_MINUS,
+    LEXER_TOKEN_SYMBOL_MULTIPLY,
+    LEXER_TOKEN_SYMBOL_DIVIDE,
+    LEXER_TOKEN_SYMBOL_MODULO,
 };
 const size_t LEXER_SYMBOL_SIZE =
     sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
@@ -119,6 +127,9 @@ LexerNodeArray lexer(char *str) {
             goto RETURN_ERROR;
           }
         }
+      } else {
+        --iter;
+        c = *iter;
       }
     }
     if (isSpace(c)) {
@@ -198,6 +209,10 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
   case LEXER_TOKEN_SYMBOL_ASSIGN:
   case LEXER_TOKEN_SYMBOL_COMMA:
   case LEXER_TOKEN_SYMBOL_PLUS:
+  case LEXER_TOKEN_SYMBOL_MINUS:
+  case LEXER_TOKEN_SYMBOL_MULTIPLY:
+  case LEXER_TOKEN_SYMBOL_DIVIDE:
+  case LEXER_TOKEN_SYMBOL_MODULO:
     if (*array_size == array->size) {
       *array_size += 1 + *array_size / 2;
       array->data =
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 6c0660f..6723cc9 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -27,6 +27,10 @@ typedef enum LexerToken {
   LEXER_TOKEN_SYMBOL_ASSIGN,
   LEXER_TOKEN_SYMBOL_COMMA,
   LEXER_TOKEN_SYMBOL_PLUS,
+  LEXER_TOKEN_SYMBOL_MINUS,
+  LEXER_TOKEN_SYMBOL_MULTIPLY,
+  LEXER_TOKEN_SYMBOL_DIVIDE,
+  LEXER_TOKEN_SYMBOL_MODULO,
 
   LEXER_TOKEN_NONE,
 } LexerToken;
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index f61836e..4b736b7 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -36,6 +36,10 @@ const char *PARSER_TOKEN_STRINGS[] = {
 
     "PARSER_TOKEN_OPERATOR_ASSIGN",
     "PARSER_TOKEN_OPERATOR_SUM",
+    "PARSER_TOKEN_OPERATOR_SUB",
+    "PARSER_TOKEN_OPERATOR_MULTIPLY",
+    "PARSER_TOKEN_OPERATOR_DIVIDE",
+    "PARSER_TOKEN_OPERATOR_MODULO",
 
     "PARSER_TOKEN_FUNCTION_DEFINITION",
 
@@ -67,7 +71,12 @@ static constexpr ParserOrder PARSER_ORDER[] = {
     },
     {
         .ltr = true,
-        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_PLUS, ),
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_MULTIPLY, LEXER_TOKEN_SYMBOL_DIVIDE,
+                    LEXER_TOKEN_SYMBOL_MODULO, ),
+    },
+    {
+        .ltr = true,
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_PLUS, LEXER_TOKEN_SYMBOL_MINUS, ),
     },
     {
         .ltr = true,
@@ -242,7 +251,11 @@ void parserNodePrint(const ParserNode *node, int indent) {
   }
     goto RETURN_SUCCESS;
   case PARSER_TOKEN_OPERATOR_ASSIGN:
-  case PARSER_TOKEN_OPERATOR_SUM: {
+  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: {
     const ParserNodeInfixMetadata *metadata = node->metadata;
     printf(",\n");
     for (int i = 0; i < indent; ++i)
@@ -342,14 +355,17 @@ void parserNodeDelete(ParserNode *node) {
   }
     goto RETURN_SUCCESS;
   case PARSER_TOKEN_OPERATOR_ASSIGN:
-  case PARSER_TOKEN_OPERATOR_SUM: {
+  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: {
     ParserNodeInfixMetadata *metadata = node->metadata;
     parserNodeDelete(metadata->left);
     parserNodeDelete(metadata->right);
     free(metadata);
   }
     goto RETURN_SUCCESS;
-
   case PARSER_TOKEN_NONE:
   }
   UNREACHABLE;
@@ -412,12 +428,13 @@ bool parserNodeArray(LexerNode *begin, LexerNode *end, ParserNode *parent) {
 
   for (LexerNode *iter = begin; iter < end; ++iter) {
     ParserNode *pNode = iter->parserNode;
-    if (pNode->parent != parent) {
-      continue;
-    } else if (pNode == NULL) {
-      printError(pNode->str_begin, pNode->str_end, "Bad child");
+    if (pNode == NULL) {
+      printError(iter->str_begin, iter->str_end, "Bad child");
       goto RETURN_ERROR;
+    } else if (pNode->parent != parent) {
+      continue;
     }
+
     for (size_t i = 0; i < parsedNodes->size; ++i) {
       if (parsedNodes->data[i] == pNode) {
         goto CONTINUE;
@@ -484,13 +501,28 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
   case LEXER_TOKEN_NUMBER:
     return parserNumber(node, parent);
   case LEXER_TOKEN_SYMBOL_ASSIGN:
-    return parserAssign(node, begin, end, parent);
+    return parserBinaryOperator(node, begin, end, parent,
+                                PARSER_TOKEN_OPERATOR_ASSIGN);
+  case LEXER_TOKEN_SYMBOL_MULTIPLY:
+    return parserBinaryOperator(node, begin, end, parent,
+                                PARSER_TOKEN_OPERATOR_MULTIPLY);
+  case LEXER_TOKEN_SYMBOL_DIVIDE:
+    return parserBinaryOperator(node, begin, end, parent,
+                                PARSER_TOKEN_OPERATOR_DIVIDE);
+  case LEXER_TOKEN_SYMBOL_MODULO:
+    return parserBinaryOperator(node, begin, end, parent,
+                                PARSER_TOKEN_OPERATOR_MODULO);
   case LEXER_TOKEN_SYMBOL_PLUS:
-    return parserPlus(node, begin, end, parent);
+    return parserBinaryOrLeftOperator(node, begin, end, parent,
+                                      PARSER_TOKEN_OPERATOR_SUM);
+  case LEXER_TOKEN_SYMBOL_MINUS:
+    return parserBinaryOrLeftOperator(node, begin, end, parent,
+                                      PARSER_TOKEN_OPERATOR_SUB);
   case LEXER_TOKEN_SYMBOL:
   case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS:
   case LEXER_TOKEN_SYMBOL_OPEN_CURLY_BRACKET:
   case LEXER_TOKEN_NONE:
+    break;
   }
   UNREACHABLE;
 }
@@ -915,7 +947,7 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
     } else {
       value = getUntilCommonParent(valueNode->parserNode, parent);
       if (!isValue(value)) {
-        printError(name->str_begin, name->str_end, "No value");
+        printError(name->str_begin, name->str_end, "Bad value");
         return NULL;
       }
       value->parent = variableNode;
@@ -943,13 +975,14 @@ RETURN_ERROR:
   return NULL;
 }
 
-ParserNode *parserAssign(LexerNode *node, LexerNode *begin, LexerNode *end,
-                         ParserNode *parent) {
+ParserNode *parserBinaryOperator(LexerNode *node, LexerNode *begin,
+                                 LexerNode *end, ParserNode *parent,
+                                 ParserToken token) {
   LexerNode *leftNode = node - 1;
   LexerNode *rightNode = node + 1;
 
   if (leftNode < begin || rightNode >= end) {
-    printError(node->str_begin, node->str_end, "Bad assign");
+    printError(node->str_begin, node->str_end, "Bad binary operator");
     return NULL;
   }
 
@@ -957,7 +990,7 @@ ParserNode *parserAssign(LexerNode *node, LexerNode *begin, LexerNode *end,
   ParserNode *right = getUntilCommonParent(rightNode->parserNode, parent);
 
   if (left == NULL || right == NULL) {
-    printError(node->str_begin, node->str_end, "Bad assign");
+    printError(node->str_begin, node->str_end, "Bad binary operator");
     return NULL;
   }
 
@@ -965,13 +998,13 @@ ParserNode *parserAssign(LexerNode *node, LexerNode *begin, LexerNode *end,
   metadata->left = left;
   metadata->right = right;
 
-  return left->parent = right->parent = node->parserNode =
-             newParserNode(PARSER_TOKEN_OPERATOR_ASSIGN, left->str_begin,
-                           right->str_end, metadata, parent);
+  return left->parent = right->parent = node->parserNode = newParserNode(
+             token, left->str_begin, right->str_end, metadata, parent);
 }
 
-ParserNode *parserPlus(LexerNode *node, LexerNode *begin, LexerNode *end,
-                       ParserNode *parent) {
+ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin,
+                                       LexerNode *end, ParserNode *parent,
+                                       ParserToken token) {
   LexerNode *leftNode = node - 1;
   LexerNode *rightNode = node + 1;
 
@@ -992,9 +1025,8 @@ ParserNode *parserPlus(LexerNode *node, LexerNode *begin, LexerNode *end,
   metadata->left = left;
   metadata->right = right;
 
-  return left->parent = right->parent = node->parserNode =
-             newParserNode(PARSER_TOKEN_OPERATOR_SUM, left->str_begin,
-                           right->str_end, metadata, parent);
+  return left->parent = right->parent = node->parserNode = newParserNode(
+             token, left->str_begin, right->str_end, metadata, parent);
 }
 
 bool isAllArguments(const ParserNodeArray *nodes) {
@@ -1019,6 +1051,10 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_KEYWORD_RETURN:
   case PARSER_TOKEN_OPERATOR_ASSIGN:
   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_VALUE_U64:
   case PARSER_TOKEN_VALUE_BOOL:
     return true;
@@ -1061,6 +1097,10 @@ bool isType(ParserNode *node) {
   case PARSER_TOKEN_KEYWORD_RETURN:
   case PARSER_TOKEN_OPERATOR_ASSIGN:
   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:
     return false;
   case PARSER_TOKEN_NONE:
   }
@@ -1076,12 +1116,16 @@ bool isValue(ParserNode *node) {
   case PARSER_TOKEN_IDENTIFIER:
   case PARSER_TOKEN_OPERATOR_ASSIGN:
   case PARSER_TOKEN_OPERATOR_SUM:
-    return true;
-  case PARSER_TOKEN_TYPE_FUNCTION:
+  case PARSER_TOKEN_OPERATOR_SUB:
+  case PARSER_TOKEN_OPERATOR_MULTIPLY:
+  case PARSER_TOKEN_OPERATOR_DIVIDE:
+  case PARSER_TOKEN_OPERATOR_MODULO:
   case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
   case PARSER_TOKEN_TYPE_BOOL:
+    return true;
+  case PARSER_TOKEN_TYPE_FUNCTION:
   case PARSER_TOKEN_CONSTANT:
   case PARSER_TOKEN_VARIABLE:
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 29a303c..0b92fe5 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -31,6 +31,10 @@ typedef enum ParserToken {
 
   PARSER_TOKEN_OPERATOR_ASSIGN,
   PARSER_TOKEN_OPERATOR_SUM,
+  PARSER_TOKEN_OPERATOR_SUB,
+  PARSER_TOKEN_OPERATOR_MULTIPLY,
+  PARSER_TOKEN_OPERATOR_DIVIDE,
+  PARSER_TOKEN_OPERATOR_MODULO,
 
   PARSER_TOKEN_FUNCTION_DEFINITION,
 
@@ -130,10 +134,11 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
                            ParserNode *parent);
 ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
                            ParserNode *parent);
-ParserNode *parserAssign(LexerNode *node, LexerNode *begin, LexerNode *end,
-                         ParserNode *parent);
-ParserNode *parserPlus(LexerNode *node, LexerNode *begin, LexerNode *end,
-                       ParserNode *parent);
+ParserNode *parserBinaryOperator(LexerNode *node, LexerNode *begin,
+                                 LexerNode *end, ParserNode *parent,
+                                 ParserToken token);
+ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin, LexerNode *end,
+                       ParserNode *parent,ParserToken token);
 
 bool isAllArguments(const ParserNodeArray *nodes);
 
-- 
cgit v1.2.3