diff --git a/src/Lib/Script/Ast/Parser/IrExpression.hh b/src/Lib/Script/Ast/Parser/IrExpression.hh index 953f2592e209bdb8fa25de7f7fd98768d014edf8..15f256df0f81232a2f2f2ba60f8ebd336e6c47c8 100644 --- a/src/Lib/Script/Ast/Parser/IrExpression.hh +++ b/src/Lib/Script/Ast/Parser/IrExpression.hh @@ -1,13 +1,7 @@ /* In: std::vector<Token>* tokens */ -auto throwUnexpectedToken = [](const Token &tok) { - throw std::runtime_error("Unexpected token in location " + tok.location().toString() + ": " + - tok.toString()); -}; - /* <|!!|> The left will be left empty (nullptr) */ -auto updateExprWithInfixOperator = [this, throwUnexpectedToken](IrExpression *¤t, - Token tok) -> void { +auto updateExprWithInfixOperator = [this](IrExpression *¤t, Token tok) -> void { /* operation -> new current, add old into right */ if (current->isInfixOperator()) throwUnexpectedToken(tok); @@ -21,15 +15,15 @@ auto updateExprWithInfixOperator = [this, throwUnexpectedToken](IrExpression *&c tok.toString()); }; -auto updateExprWithConstExpr = [this](IrExpression *¤t, Token tok) -> void { - IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok); - +auto updateExprWithSimpleExpression = [this](IrExpression *¤t, IrExpression *newLeft, + const Token tok) -> void { /* (... `op` <- currentExpression) newLeft -> currentExpression */ if (current != nullptr) { switch (current->type()) { 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"); @@ -41,8 +35,32 @@ auto updateExprWithConstExpr = [this](IrExpression *¤t, Token tok) -> void current = newLeft; }; +auto updateExprWithConstExpr = [updateExprWithSimpleExpression](IrExpression *¤t, + const Token tok) -> void { + IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok); + updateExprWithSimpleExpression(current, newLeft, tok); +}; + volatile ssize_t expressionScopeLevel = 0; +auto parseExprList = [this](std::vector<Token> *tokens, StrV endToken, + auto &parseNextExpression) -> std::vector<IrExpression *> { + bool hasNextArgument = false; + std::vector<IrExpression *> list; + do { + list.push_back(parseNextExpression(tokens, parseNextExpression)); + const auto maybeToken = tokenListPeek(tokens); + hasNextArgument = + maybeToken.has_value() && getInnerTokenOpt(maybeToken).isSimple(TOKEN_COMMA); + } while (hasNextArgument); + if (const Token endTokenFromList = getInnerTokenOpt(tokenListPop(tokens)); + !endTokenFromList.isSimple(endToken)) { + throwUnexpectedToken(endTokenFromList, "Expected a token to end the list of expression: " + + endToken.toStdString()); + } + return list; +}; + /* ** a + b + c + d + e ==> (e + (d + (c + (b + a)))) ** first : simple @@ -50,9 +68,9 @@ volatile ssize_t expressionScopeLevel = 0; ** parse tokens => new expr, take current, add to left */ -auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, throwUnexpectedToken, - updateExprWithInfixOperator](std::vector<Token> *tokens, - auto &itSelf) -> IrExpression * { +auto parseNextExpression = [this, &expressionScopeLevel, updateExprWithSimpleExpression, + updateExprWithConstExpr, parseExprList, updateExprWithInfixOperator]( + std::vector<Token> *tokens, auto &itSelf) -> IrExpression * { const ssize_t expressionScopeLevelAtLaunchTime = expressionScopeLevel; IrExpression *currentExpression = nullptr; @@ -65,8 +83,47 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro switch (firstToken.valueType()) { case Token::Type::QNAME: { - // Function Call or Variable Ref - throw std::logic_error("QNAME not handled (call or var)"); + tokenListPop(tokens); /* Pop the variable or function name */ + const std::optional<Token> maybeNext = tokenListPeekNext(tokens); + /* A function call or a variable with indexes */ + if (maybeNext.has_value()) { + const Token nextToken = getInnerTokenOpt(maybeNext); + tokenListPop(tokens); /* Pop the maybe ( or [ token */ + + /* A function call: functionName( ... */ + if (nextToken.isSimple(TOKEN_PARENT_LEFT)) { + updateExprWithSimpleExpression( + currentExpression, + IrElement::create<IrECall>( + nullptr, parentScope()->getFunctionByName(firstToken.asQName()), + parseExprList(tokens, TOKEN_PARENT_RIGHT, itSelf)), + firstToken); + } + + /* A variable with indexes: varName[ ... */ + else if (nextToken.isSimple(TOKEN_BRACKET_LEFT)) { + updateExprWithSimpleExpression( + currentExpression, + IrElement::create<IrEVariableRef>( + nullptr, parentScope()->getVariableByName(firstToken.asQName()), + parseExprList(tokens, TOKEN_BRACKET_RIGHT, itSelf)), + firstToken); + } + + else { + throwUnexpectedToken(nextToken, "expected a bracket for a variable " + "with indices or a paren for a function call"); + } + } + + /* A simple variable, with no indexes or whatever */ + else { + updateExprWithSimpleExpression( + currentExpression, + IrElement::create<IrEVariableRef>( + nullptr, parentScope()->getVariableByName(firstToken.asQName())), + firstToken); + } break; } @@ -91,7 +148,8 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro /* New element in a function call */ else if (firstToken.isSimple(TOKEN_COMMA)) { - throw std::runtime_error("Multi-arg function calls not handled"); + expressionScopeLevel = expressionScopeLevel - 1; + return currentExpression; } /* Create arithmetic operation */