diff --git a/src/Lib/Script/Ast/IrElement.cc b/src/Lib/Script/Ast/IrElement.cc index 94dfb5f3926f6721b80335acd2597b8690cc0fd6..155957c2a3c3179802c082221ccf1d41a732309b 100644 --- a/src/Lib/Script/Ast/IrElement.cc +++ b/src/Lib/Script/Ast/IrElement.cc @@ -6,6 +6,13 @@ namespace Vivy::Script { IrElement::IrElement(IrElement *p) noexcept { setParent(p); } +void +IrElement::throwUnexpectedToken(const Token &tok) const +{ + throw std::runtime_error("Unexpected token in location " + tok.location().toString() + ": " + + tok.toString()); +} + IrElement::~IrElement() noexcept { std::erase_if(childElements, [this](IrElement *child) noexcept -> bool { diff --git a/src/Lib/Script/Ast/IrElement.hh b/src/Lib/Script/Ast/IrElement.hh index 00503dcf7aec2fab5638ad7d6c28fd27b8ff3ec2..4e0e13fce1b3628d6487a86bd6500aa793454d2d 100644 --- a/src/Lib/Script/Ast/IrElement.hh +++ b/src/Lib/Script/Ast/IrElement.hh @@ -116,6 +116,8 @@ protected: void detachElementFromParent() noexcept; void addChild(IrElement *) noexcept; + void throwUnexpectedToken(const Token &tok) const; + public: virtual ~IrElement() noexcept; diff --git a/src/Lib/Script/Ast/IrExpression.cc b/src/Lib/Script/Ast/IrExpression.cc index a2b1faf01cf8fd87ccc0a52c112cedbd840ae6bc..8aa191c4d718408d07abe7bcae57aacf01ac8b00 100644 --- a/src/Lib/Script/Ast/IrExpression.cc +++ b/src/Lib/Script/Ast/IrExpression.cc @@ -242,8 +242,20 @@ IrECall::args() const noexcept } } +/* +** IrECompOp +*/ + namespace Vivy::Script { +IrECompOp::IrECompOp(OpType type, IrExpression *&&leftA, IrExpression *&&rightA) noexcept + : IrExpression(nullptr, Type::ArithmeticOp) + , selfOpType(type) + , left(leftA) + , right(rightA) +{ +} + std::string IrECompOp::toString() const noexcept { @@ -251,8 +263,21 @@ IrECompOp::toString() const noexcept } } +/* +** IrEArithmeticOp +*/ + namespace Vivy::Script { +IrEArithmeticOp::IrEArithmeticOp(OpType type, IrExpression *&&leftA, + IrExpression *&&rightA) noexcept + : IrExpression(nullptr, Type::ArithmeticOp) + , selfOpType(type) + , left(leftA) + , right(rightA) +{ +} + std::string IrEArithmeticOp::toString() const noexcept { @@ -260,8 +285,20 @@ IrEArithmeticOp::toString() const noexcept } } +/* +** IrELogicOp +*/ + namespace Vivy::Script { +IrELogicOp::IrELogicOp(OpType type, IrExpression *&&leftA, IrExpression *&&rightA) noexcept + : IrExpression(nullptr, Type::LogicOp) + , selfOpType(type) + , left(leftA) + , right(rightA) +{ +} + std::string IrELogicOp::toString() const noexcept { @@ -269,6 +306,10 @@ IrELogicOp::toString() const noexcept } } +/* +** Free functions +*/ + namespace Vivy::Script { std::string @@ -307,6 +348,10 @@ toString(IrECompOp::OpType op) noexcept } } +/* +** Binary expressions' type from tokens +*/ + namespace Vivy::Script { IrELogicOp::OpType diff --git a/src/Lib/Script/Ast/IrExpression.hh b/src/Lib/Script/Ast/IrExpression.hh index 36458dd7c61aaf9c2becb251e665dce26e17e02d..c2ff6f9d72f0d69215d15645fc4f7e06d7e55bf1 100644 --- a/src/Lib/Script/Ast/IrExpression.hh +++ b/src/Lib/Script/Ast/IrExpression.hh @@ -20,6 +20,35 @@ private: Type selfType; IrType *selfInnerType = nullptr; + /* + ** Helper for the parser, create a binary expression, insert the last expression at + ** the right and update the current expression pointer. + */ + + template <typename IrT> IrExpression *createOpElement(IrExpression *¤t, Token tok) + { + return dynamic_cast<IrExpression *>( + IrElement::create<IrT>(nullptr, /* The parent, will be set later */ + IrT::getOpFromToken(tok), /* The type of operation (+,-,...) */ + std::move(nullptr), /* We leave the left empty for now */ + std::move(current) /* We add everything to the right */ + )); + } + + /* + ** Helper for the parser, update the left expression of a binary expression or throw + ** an error if there was already somthing. + */ + + template <typename IrT> void updateLeft(IrExpression *current, IrExpression *newLeft, Token tok) + { + IrT *typpedCurrent = dynamic_cast<IrT *>(current); + if (typpedCurrent->left != nullptr) + throw std::runtime_error("Unexpected token in expression parsing: " + tok.toString()); + typpedCurrent->left = newLeft; + newLeft->setParent(current); + } + protected: IrExpression(IrElement *p, Type) noexcept; diff --git a/src/Lib/Script/Ast/Parser/IrExpression.hh b/src/Lib/Script/Ast/Parser/IrExpression.hh index 8713a3021628da8a991c70a4ca70ea0399fcb74b..953f2592e209bdb8fa25de7f7fd98768d014edf8 100644 --- a/src/Lib/Script/Ast/Parser/IrExpression.hh +++ b/src/Lib/Script/Ast/Parser/IrExpression.hh @@ -5,47 +5,31 @@ auto throwUnexpectedToken = [](const Token &tok) { tok.toString()); }; -auto createOpElement = []<typename IrT>(IrExpression *¤t, Token tok) -> IrT* { - return dynamic_cast<IrExpression *>(IrElement::create<IrT>( - nullptr, /* The parent, will be set later */ - IrT::getOpFromToken(tok), /* The type of operation (+,-,...) */ - std::move(nullptr), /* We leave the left empty for now */ - std::move(current) /* We add everything to the right */ - )); -}; - /* <|!!|> The left will be left empty (nullptr) */ -auto updateExprWithInfixOperator = [throwUnexpectedToken, createOpElement]( - IrExpression *¤t, Token tok) -> void -{ +auto updateExprWithInfixOperator = [this, 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)) ? createOpElement<IrEArithmeticOp>(current, tok) - : (tok.isSimple(TOKEN_LIST_LOGIC_OP)) ? createOpElement<IrELogicOp>(current, tok) - : (tok.isSimple(TOKEN_LIST_COMP_OP)) ? createOpElement<IrECompOp>(current, tok) - : throw std::runtime_error("Can't create an infix operation from token " + tok.toString()); -}; - -auto updateLeft = []<typename IrT>(IrExpression *current, IrExpression *newLeft) -> void { - IrT *typpedCurrent = dynamic_cast<IrT *>(current); - if (typpedCurrent->left != nullptr) - throw std::runtime_error("Unexpected token in expression parsing: " + tok.toString()); - typpedCurrent->left = newLeft; - newLeft->setParent(current); + current = (tok.isSimple(TOKEN_LIST_ARITHMETIC_OP)) + ? createOpElement<IrEArithmeticOp>(current, tok) + : (tok.isSimple(TOKEN_LIST_LOGIC_OP)) ? createOpElement<IrELogicOp>(current, tok) + : (tok.isSimple(TOKEN_LIST_COMP_OP)) + ? createOpElement<IrECompOp>(current, tok) + : throw std::runtime_error("Can't create an infix operation from token " + + tok.toString()); }; -auto updateExprWithConstExpr = [updateLeft](IrExpression *¤t, Token tok) -> void { +auto updateExprWithConstExpr = [this](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: return <IrECompOp>(current, newLeft); - case Type::ArithmeticOp: return updateLeft<IrEArithmeticOp>(current, newLeft); - case Type::LogicOp: return updateLeft<IrELogicOp>(current, newLeft); + case Type::CompOp: return updateLeft<IrECompOp>(current, newLeft, tok); + case Type::ArithmeticOp: return updateLeft<IrEArithmeticOp>(current, newLeft, tok); + case Type::LogicOp: return updateLeft<IrELogicOp>(current, newLeft, tok); case Type::ConstExpr: case Type::Call: case Type::VariableRef: throw std::runtime_error("Invalid expression");