diff --git a/src/Lib/Script/Ast/IrExpression.cc b/src/Lib/Script/Ast/IrExpression.cc
index ff8fd6093c8782f1e11e507a68117598c99819a7..d7c2ce71c337b734b8fc2bb73c81f2261d11bd7a 100644
--- a/src/Lib/Script/Ast/IrExpression.cc
+++ b/src/Lib/Script/Ast/IrExpression.cc
@@ -306,3 +306,21 @@ toString(IrECompOp::OpType op) noexcept
     }
 }
 }
+
+namespace Vivy::Script
+{
+IrELogicOp::OpType
+IrELogicOp::getOpFromToken(Token tok)
+{
+}
+
+IrECompOp::OpType
+IrECompOp::getOpFromToken(Token tok)
+{
+}
+
+IrEArithmeticOp::OpType
+IrEArithmeticOp::getOpFromToken(Token tok)
+{
+}
+}
diff --git a/src/Lib/Script/Ast/IrExpression.hh b/src/Lib/Script/Ast/IrExpression.hh
index c62ddd11352ce57810c25b5bac3d560b38c57b49..36458dd7c61aaf9c2becb251e665dce26e17e02d 100644
--- a/src/Lib/Script/Ast/IrExpression.hh
+++ b/src/Lib/Script/Ast/IrExpression.hh
@@ -78,6 +78,7 @@ class IrECompOp : public IrExpression {
 
 public:
     enum class OpType { LT, GT, LE, GE, EQ, NEQ };
+    static OpType getOpFromToken(Token);
 
 private:
     const OpType selfOpType;
@@ -97,6 +98,7 @@ class IrEArithmeticOp : public IrExpression {
 
 public:
     enum class OpType { Add, Sub, Mul, Div, Mod };
+    static OpType getOpFromToken(Token);
 
 private:
     const OpType selfOpType;
@@ -116,6 +118,7 @@ class IrELogicOp : public IrExpression {
 
 public:
     enum class OpType { And, Or, Xor };
+    static OpType getOpFromToken(Token);
 
 private:
     const OpType selfOpType;
diff --git a/src/Lib/Script/Ast/Parser/IrExpression.hh b/src/Lib/Script/Ast/Parser/IrExpression.hh
index ab380e221c679c9c064fe8de85517d137ba44ad3..e4caa0f4eeb3033241ec70eb2305cad451b8b44a 100644
--- a/src/Lib/Script/Ast/Parser/IrExpression.hh
+++ b/src/Lib/Script/Ast/Parser/IrExpression.hh
@@ -5,6 +5,27 @@ auto throwUnexpectedToken = [](const Token &tok) {
                              tok.toString());
 };
 
+/* <|!!|> The left will be left empty (nullptr) */
+auto updateExprWithInfixOperator = [throwUnexpectedToken](IrExpression *&current,
+                                                          Token tok) -> void {
+    /* operation -> new current, add old into right */
+    if (current->isInfixOperator())
+        throwUnexpectedToken(tok);
+
+    current =
+        (tok.isSimple(TOKEN_LIST_ARITHMETIC_OP))
+            ? dynamic_cast<IrExpression *>(
+                  IrElement::create<IrEArithmeticOp>(nullptr, IrEArithmeticOp::getOpFromToken(tok),
+                                                     std::move(current), std::move(nullptr)))
+        : (tok.isSimple(TOKEN_LIST_LOGIC_OP))
+            ? dynamic_cast<IrExpression *>(IrElement::create<IrELogicOp>(
+                  nullptr, IrELogicOp::getOpFromToken(tok), std::move(current), std::move(nullptr)))
+        : (tok.isSimple(TOKEN_LIST_COMP_OP))
+            ? dynamic_cast<IrExpression *>(IrElement::create<IrECompOp>(
+                  nullptr, IrECompOp::getOpFromToken(tok), std::move(current), std::move(nullptr)))
+            : nullptr;
+};
+
 auto updateExprWithConstExpr = [](IrExpression *&current, Token tok) -> void {
     IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok);
     /* (... `op` <- currentExpression) newLeft -> currentExpression */
@@ -33,8 +54,9 @@ volatile ssize_t expressionScopeLevel = 0;
 ** parse tokens => new expr, take current, add to left
 */
 
-auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr](
-                               std::vector<Token> *tokens, auto &itSelf) -> IrExpression * {
+auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, throwUnexpectedToken,
+                            updateExprWithInfixOperator](std::vector<Token> *tokens,
+                                                         auto &itSelf) -> IrExpression * {
     const ssize_t expressionScopeLevelAtLaunchTime = expressionScopeLevel;
     IrExpression *currentExpression                = nullptr;
 
@@ -65,9 +87,29 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr](
                 updateExprWithConstExpr(currentExpression, firstToken);
             }
 
-            else {
-                // operation -> new current, add old into right
+            /* End a function call */
+            else if (firstToken.isSimple(TOKEN_PARENT_RIGHT)) {
+                expressionScopeLevel = expressionScopeLevel - 1;
+                return currentExpression;
+            }
+
+            /* New element in a function call */
+            else if (firstToken.isSimple(TOKEN_COMMA)) {
+                throw std::runtime_error("Multi-arg function calls not handled");
             }
+
+            /* Create arithmetic operation */
+            else if (firstToken.isSimple(TOKEN_LIST_ARITHMETIC_OP)) {
+                updateExprWithInfixOperator(currentExpression, firstToken);
+            }
+
+            /* Create logic operation */
+            else if (firstToken.isSimple(TOKEN_LIST_LOGIC_OP)) {
+                updateExprWithInfixOperator(currentExpression, firstToken);
+            }
+
+            else
+                throwUnexpectedToken(firstToken);
             break;
         }
         }
diff --git a/src/Lib/Script/FrontEnd/Tokens.hh b/src/Lib/Script/FrontEnd/Tokens.hh
index 6868074d04dca2531d5d75df42d40a6373250652..57c983a4fecaba08f83a926fc38471ae0d02d9cf 100644
--- a/src/Lib/Script/FrontEnd/Tokens.hh
+++ b/src/Lib/Script/FrontEnd/Tokens.hh
@@ -61,6 +61,21 @@ namespace Vivy::Script
 #define TOKEN_FUNCTION            STRV_STATIC("function")
 #define TOKEN_JOB                 STRV_STATIC("job")
 
+#define TOKEN_LIST_LOGIC_OP \
+    {                       \
+        TOKEN_AND, TOKEN_OR \
+    }
+
+#define TOKEN_LIST_ARITHMETIC_OP                                   \
+    {                                                              \
+        TOKEN_PLUS, TOKEN_MINUS, TOKEN_DIV, TOKEN_TIMES, TOKEN_MOD \
+    }
+
+#define TOKEN_LIST_COMP_OP                                          \
+    {                                                               \
+        TOKEN_EQ, TOKEN_NEQ, TOKEN_LT, TOKEN_LE, TOKEN_GT, TOKEN_GE \
+    }
+
 #define TOKEN_LIST_BASE_TYPE                                                     \
     {                                                                            \
         TOKEN_BOOL, TOKEN_REAL, TOKEN_INT, TOKEN_COLOR, TOKEN_VOID, TOKEN_STRING \