Parse function call

This commit is contained in:
Rafał Grodziński
2025-06-18 15:31:04 +09:00
parent 20a3adcca2
commit cbd8daf219
5 changed files with 74 additions and 1 deletions

View File

@@ -246,6 +246,34 @@ string ExpressionVar::toString(int indent) {
return "VAR(" + name + ")";
}
//
// Expression Call
ExpressionCall::ExpressionCall(string name, vector<shared_ptr<Expression>> argumentExpressions):
Expression(ExpressionKind::CALL, ValueType::NONE), name(name), argumentExpressions(argumentExpressions) {
}
string ExpressionCall::getName() {
return name;
}
vector<shared_ptr<Expression>> ExpressionCall::getArgumentExpressions() {
return argumentExpressions;
}
string ExpressionCall::toString(int indent) {
string value;
value += "CALL(" + name + "):";
for (shared_ptr<Expression> &argumentExpression : argumentExpressions) {
value += "\n";
for (int ind=0; ind<indent+1; ind++)
value += " ";
value += argumentExpression->toString(indent+1) + ",";
}
return value;
}
//
// ExpressionInvalid
ExpressionInvalid::ExpressionInvalid(shared_ptr<Token> token):

View File

@@ -114,6 +114,20 @@ public:
string toString(int indent) override;
};
//
// Expression Call
class ExpressionCall: public Expression {
private:
string name;
vector<shared_ptr<Expression>> argumentExpressions;
public:
ExpressionCall(string name, vector<shared_ptr<Expression>> argumentExpressions);
string getName();
vector<shared_ptr<Expression>> getArgumentExpressions();
string toString(int indent) override;
};
//
// ExpressionInvalid
class ExpressionInvalid: public Expression {

View File

@@ -264,6 +264,10 @@ shared_ptr<Expression> Parser::matchPrimary() {
expression = matchExpressionLiteral();
if (expression != nullptr)
return expression;
expression = matchExpressionCall();
if (expression != nullptr)
return expression;
expression = matchExpressionVar();
if (expression != nullptr)
@@ -359,7 +363,7 @@ shared_ptr<Expression> Parser::matchExpressionIfElse() {
shared_ptr<Statement> elseBlock;
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
bool isSingleLine = !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
vector<TokenKind> terminalTokens = {TokenKind::SEMICOLON};
vector<TokenKind> terminalTokens = {TokenKind::SEMICOLON, TokenKind::COMMA, TokenKind::RIGHT_PAREN};
if (isSingleLine)
terminalTokens.push_back(TokenKind::NEW_LINE);
@@ -383,6 +387,31 @@ shared_ptr<Expression> Parser::matchExpressionVar() {
return nullptr;
}
shared_ptr<Expression> Parser::matchExpressionCall() {
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::LEFT_PAREN}, true, false))
return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex);
currentIndex++; // identifier
currentIndex++; // left parenthesis
vector<shared_ptr<Expression>> argumentExpressions;
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // optional new line
shared_ptr<Expression> argumentExpression = nextExpression();
if (argumentExpression == nullptr || !argumentExpression->isValid())
return argumentExpression;
argumentExpressions.push_back(argumentExpression);
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // optional new line
if (!tryMatchingTokenKinds({TokenKind::RIGHT_PAREN}, true, true))
return matchExpressionInvalid();
return make_shared<ExpressionCall>(identifierToken->getLexme(), argumentExpressions);
}
shared_ptr<ExpressionInvalid> Parser::matchExpressionInvalid() {
return make_shared<ExpressionInvalid>(tokens.at(currentIndex));
}

View File

@@ -34,6 +34,7 @@ private:
shared_ptr<Expression> matchExpressionBinary(shared_ptr<Expression> left);
shared_ptr<Expression> matchExpressionIfElse();
shared_ptr<Expression> matchExpressionVar();
shared_ptr<Expression> matchExpressionCall();
shared_ptr<ExpressionInvalid> matchExpressionInvalid();
bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance);

View File

@@ -46,6 +46,7 @@ enum class ExpressionKind {
BINARY,
IF_ELSE,
VAR,
CALL,
INVALID
};