Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 91a75ea5 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

WIP: Continue the parse expression function

Now should be able to parse function calls and variable references with
and without indices.
parent dcaaa4de
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!25Draft: New Vivy module spec
Pipeline #2874 en échec
/* In: std::vector<Token>* tokens */ /* 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) */ /* <|!!|> The left will be left empty (nullptr) */
auto updateExprWithInfixOperator = [this, throwUnexpectedToken](IrExpression *&current, auto updateExprWithInfixOperator = [this](IrExpression *&current, Token tok) -> void {
Token tok) -> void {
/* operation -> new current, add old into right */ /* operation -> new current, add old into right */
if (current->isInfixOperator()) if (current->isInfixOperator())
throwUnexpectedToken(tok); throwUnexpectedToken(tok);
...@@ -21,15 +15,15 @@ auto updateExprWithInfixOperator = [this, throwUnexpectedToken](IrExpression *&c ...@@ -21,15 +15,15 @@ auto updateExprWithInfixOperator = [this, throwUnexpectedToken](IrExpression *&c
tok.toString()); tok.toString());
}; };
auto updateExprWithConstExpr = [this](IrExpression *&current, Token tok) -> void { auto updateExprWithSimpleExpression = [this](IrExpression *&current, IrExpression *newLeft,
IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok); const Token tok) -> void {
/* (... `op` <- currentExpression) newLeft -> currentExpression */ /* (... `op` <- currentExpression) newLeft -> currentExpression */
if (current != nullptr) { if (current != nullptr) {
switch (current->type()) { switch (current->type()) {
case Type::CompOp: return updateLeft<IrECompOp>(current, newLeft, tok); case Type::CompOp: return updateLeft<IrECompOp>(current, newLeft, tok);
case Type::ArithmeticOp: return updateLeft<IrEArithmeticOp>(current, newLeft, tok); case Type::ArithmeticOp: return updateLeft<IrEArithmeticOp>(current, newLeft, tok);
case Type::LogicOp: return updateLeft<IrELogicOp>(current, newLeft, tok); case Type::LogicOp: return updateLeft<IrELogicOp>(current, newLeft, tok);
case Type::ConstExpr: case Type::ConstExpr:
case Type::Call: case Type::Call:
case Type::VariableRef: throw std::runtime_error("Invalid expression"); case Type::VariableRef: throw std::runtime_error("Invalid expression");
...@@ -41,8 +35,32 @@ auto updateExprWithConstExpr = [this](IrExpression *&current, Token tok) -> void ...@@ -41,8 +35,32 @@ auto updateExprWithConstExpr = [this](IrExpression *&current, Token tok) -> void
current = newLeft; current = newLeft;
}; };
auto updateExprWithConstExpr = [updateExprWithSimpleExpression](IrExpression *&current,
const Token tok) -> void {
IrExpression *newLeft = IrElement::create<IrEConstExpr>(current, tok);
updateExprWithSimpleExpression(current, newLeft, tok);
};
volatile ssize_t expressionScopeLevel = 0; 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)))) ** a + b + c + d + e ==> (e + (d + (c + (b + a))))
** first : simple ** first : simple
...@@ -50,9 +68,9 @@ volatile ssize_t expressionScopeLevel = 0; ...@@ -50,9 +68,9 @@ volatile ssize_t expressionScopeLevel = 0;
** parse tokens => new expr, take current, add to left ** parse tokens => new expr, take current, add to left
*/ */
auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, throwUnexpectedToken, auto parseNextExpression = [this, &expressionScopeLevel, updateExprWithSimpleExpression,
updateExprWithInfixOperator](std::vector<Token> *tokens, updateExprWithConstExpr, parseExprList, updateExprWithInfixOperator](
auto &itSelf) -> IrExpression * { std::vector<Token> *tokens, auto &itSelf) -> IrExpression * {
const ssize_t expressionScopeLevelAtLaunchTime = expressionScopeLevel; const ssize_t expressionScopeLevelAtLaunchTime = expressionScopeLevel;
IrExpression *currentExpression = nullptr; IrExpression *currentExpression = nullptr;
...@@ -65,8 +83,47 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro ...@@ -65,8 +83,47 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro
switch (firstToken.valueType()) { switch (firstToken.valueType()) {
case Token::Type::QNAME: { case Token::Type::QNAME: {
// Function Call or Variable Ref tokenListPop(tokens); /* Pop the variable or function name */
throw std::logic_error("QNAME not handled (call or var)"); 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; break;
} }
...@@ -91,7 +148,8 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro ...@@ -91,7 +148,8 @@ auto parseNextExpression = [&expressionScopeLevel, updateExprWithConstExpr, thro
/* New element in a function call */ /* New element in a function call */
else if (firstToken.isSimple(TOKEN_COMMA)) { else if (firstToken.isSimple(TOKEN_COMMA)) {
throw std::runtime_error("Multi-arg function calls not handled"); expressionScopeLevel = expressionScopeLevel - 1;
return currentExpression;
} }
/* Create arithmetic operation */ /* Create arithmetic operation */
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter