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 *¤t, + 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 *¤t, 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 \