diff --git a/src/Lib/Script/Ast/IrExpression.cc b/src/Lib/Script/Ast/IrExpression.cc index f2111cdd6085557966c7a0f19fe316cf9e9edc2f..ff8fd6093c8782f1e11e507a68117598c99819a7 100644 --- a/src/Lib/Script/Ast/IrExpression.cc +++ b/src/Lib/Script/Ast/IrExpression.cc @@ -44,8 +44,14 @@ IrExpression::toString() const noexcept assert(false && "Unreachable"); } +bool +IrExpression::isInfixOperator() const noexcept +{ + return (type() == Type::CompOp) || (type() == Type::ArithmeticOp) || (type() == Type::LogicOp); +} + void -IrExpression::parse(std::vector<Token> *tokens) +IrExpression::parse(std::vector<Token> *argTokens) { #include "Parser/IrExpression.hh" } diff --git a/src/Lib/Script/Ast/IrExpression.hh b/src/Lib/Script/Ast/IrExpression.hh index 6f92db8ad7cff25bc52123738cccb786b2ccfdeb..c62ddd11352ce57810c25b5bac3d560b38c57b49 100644 --- a/src/Lib/Script/Ast/IrExpression.hh +++ b/src/Lib/Script/Ast/IrExpression.hh @@ -6,6 +6,10 @@ namespace Vivy::Script { +#define VIVY_IR_EXPRESSION(clazz) \ + VIVY_IR_ELEMENT(clazz) \ + friend class IrExpression; + class IrExpression : public IrElement { VIVY_IR_ELEMENT(IrExpression) @@ -27,11 +31,12 @@ public: void parse(std::vector<Token> *); Type type() const noexcept; + bool isInfixOperator() const noexcept; virtual IrType *innerType() const noexcept; }; class IrEConstExpr : public IrExpression { - VIVY_IR_ELEMENT(IrEConstExpr) + VIVY_IR_EXPRESSION(IrEConstExpr) IrEConstExpr(const Token &); @@ -56,7 +61,7 @@ public: }; class IrECall : public IrExpression { - VIVY_IR_ELEMENT(IrECall) + VIVY_IR_EXPRESSION(IrECall) IrFunction *callPtr = nullptr; std::vector<IrExpression *> inArgs; @@ -69,7 +74,7 @@ public: }; class IrECompOp : public IrExpression { - VIVY_IR_ELEMENT(IrECompOp) + VIVY_IR_EXPRESSION(IrECompOp) public: enum class OpType { LT, GT, LE, GE, EQ, NEQ }; @@ -88,7 +93,7 @@ public: }; class IrEArithmeticOp : public IrExpression { - VIVY_IR_ELEMENT(IrEArithmeticOp) + VIVY_IR_EXPRESSION(IrEArithmeticOp) public: enum class OpType { Add, Sub, Mul, Div, Mod }; @@ -107,7 +112,7 @@ public: }; class IrELogicOp : public IrExpression { - VIVY_IR_ELEMENT(IrELogicOp) + VIVY_IR_EXPRESSION(IrELogicOp) public: enum class OpType { And, Or, Xor }; @@ -126,7 +131,7 @@ public: }; class IrEVariableRef : public IrExpression { - VIVY_IR_ELEMENT(IrEVariableRef) + VIVY_IR_EXPRESSION(IrEVariableRef) IrVariable *const referencedVariable; std::vector<IrExpression *> indicies; diff --git a/src/Lib/Script/Ast/Parser/IrExpression.hh b/src/Lib/Script/Ast/Parser/IrExpression.hh index 57bcbd04f159a56da4ed0783af1c007e30ad011a..ab380e221c679c9c064fe8de85517d137ba44ad3 100644 --- a/src/Lib/Script/Ast/Parser/IrExpression.hh +++ b/src/Lib/Script/Ast/Parser/IrExpression.hh @@ -1,3 +1,80 @@ /* In: std::vector<Token>* tokens */ +auto throwUnexpectedToken = [](const Token &tok) { + throw std::runtime_error("Unexpected token in location " + tok.location().toString() + ": " + + tok.toString()); +}; + +auto updateExprWithConstExpr = [](IrExpression *¤t, Token tok) -> void { + IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok); + /* (... `op` <- currentExpression) newLeft -> currentExpression */ + if (current != nullptr) { + switch (current->type()) { + case Type::CompOp: dynamic_cast<IrECompOp *>(current)->left = newLeft; return; + case Type::ArithmeticOp: dynamic_cast<IrEArithmeticOp *>(current)->left = newLeft; return; + case Type::LogicOp: dynamic_cast<IrELogicOp *>(current)->left = newLeft; return; + case Type::ConstExpr: + case Type::Call: + case Type::VariableRef: throw std::runtime_error("Invalid expression"); + } + } + + /* newLeft -> currentExpression */ + else + current = newLeft; +}; + +volatile ssize_t expressionScopeLevel = 0; + +/* +** a + b + c + d + e ==> (e + (d + (c + (b + a)))) +** first : simple +** find op, parse the next token +** parse tokens => new expr, take current, add to left +*/ + +auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr]( + std::vector<Token> *tokens, auto &itSelf) -> IrExpression * { + const ssize_t expressionScopeLevelAtLaunchTime = expressionScopeLevel; + IrExpression *currentExpression = nullptr; + + while (tokenListIsNotEmpty(tokens) && + (expressionScopeLevelAtLaunchTime < expressionScopeLevel)) { + const std::optional<Token> maybeFirstToken = tokenListPeek(tokens); + if (!maybeFirstToken.has_value()) + return nullptr; + const Token firstToken = getInnerTokenOpt(maybeFirstToken); + + switch (firstToken.valueType()) { + case Token::Type::QNAME: { + // Function Call or Variable Ref + throw std::logic_error("QNAME not handled (call or var)"); + break; + } + + case Token::Type::COLORLIT: + case Token::Type::INTEGER: + case Token::Type::FLOATING: + case Token::Type::STRINGLIT: { + updateExprWithConstExpr(currentExpression, firstToken); + break; + } + + case Token::Type::SIMPLE: { + if (firstToken.isSimple(TOKEN_TRUE) || firstToken.isSimple(TOKEN_FALSE)) { + updateExprWithConstExpr(currentExpression, firstToken); + } + + else { + // operation -> new current, add old into right + } + break; + } + } + } + + return currentExpression; +}; + +parseNextExpression(argTokens, parseNextExpression); throw std::logic_error("Parser/IrExpression: Not implemented"); diff --git a/src/Lib/Script/Ast/Parser/IrInstruction.hh b/src/Lib/Script/Ast/Parser/IrInstruction.hh index f3f3810d4d72965da1c9f26f3c3d3b22b796726d..7436ec6d9ba516638f4a3b47a817fd98bf0146a6 100644 --- a/src/Lib/Script/Ast/Parser/IrInstruction.hh +++ b/src/Lib/Script/Ast/Parser/IrInstruction.hh @@ -28,6 +28,7 @@ auto parseNextInstruction = [&instructionScopeLevel]( auto &itSelf /* The lambda itself, for recursion */ ) { if (tokenListIsEmpty(tokens)) { + throw std::runtime_error("Implement void instruction"); /* Create a `return void` instruction */ }