Parse function arguments and return type

This commit is contained in:
Rafał Grodziński
2025-06-16 11:29:30 +09:00
parent 8579de4fba
commit 20a3adcca2
10 changed files with 96 additions and 63 deletions

View File

@@ -23,7 +23,7 @@ string Expression::toString(int indent) {
//
// ExpressionBinary
ExpressionBinary::ExpressionBinary(shared_ptr<Token> token, shared_ptr<Expression> left, shared_ptr<Expression> right):
Expression(ExpressionKind::BINARY, ValueType::VOID), left(left), right(right) {
Expression(ExpressionKind::BINARY, ValueType::NONE), left(left), right(right) {
// Types must match
if (left->getValueType() != right->getValueType())
exit(1);
@@ -124,7 +124,7 @@ string ExpressionBinary::toString(int indent) {
//
// ExpressionLiteral
ExpressionLiteral::ExpressionLiteral(shared_ptr<Token> token):
Expression(ExpressionKind::LITERAL, ValueType::VOID) {
Expression(ExpressionKind::LITERAL, ValueType::NONE) {
switch (token->getKind()) {
case TokenKind::BOOL:
boolValue = token->getLexme().compare("true") == 0;
@@ -157,8 +157,8 @@ float ExpressionLiteral::getReal32Value() {
string ExpressionLiteral::toString(int indent) {
switch (valueType) {
case ValueType::VOID:
return "VOID";
case ValueType::NONE:
return "NONE";
case ValueType::BOOL:
return boolValue ? "true" : "false";
case ValueType::SINT32:
@@ -185,7 +185,7 @@ string ExpressionGrouping::toString(int indent) {
//
// ExpressionIfElse
ExpressionIfElse::ExpressionIfElse(shared_ptr<Expression> condition, shared_ptr<StatementBlock> thenBlock, shared_ptr<StatementBlock> elseBlock):
Expression(ExpressionKind::IF_ELSE, ValueType::VOID), condition(condition), thenBlock(thenBlock), elseBlock(elseBlock) {
Expression(ExpressionKind::IF_ELSE, ValueType::NONE), condition(condition), thenBlock(thenBlock), elseBlock(elseBlock) {
// Condition must evaluate to bool
if (condition->getValueType() != ValueType::BOOL)
exit(1);
@@ -199,7 +199,7 @@ Expression(ExpressionKind::IF_ELSE, ValueType::VOID), condition(condition), then
exit(1);
// get type or default to void
valueType = thenExpression ? thenExpression->getValueType() : ValueType::VOID;
valueType = thenExpression ? thenExpression->getValueType() : ValueType::NONE;
}
shared_ptr<Expression> ExpressionIfElse::getCondition() {
@@ -235,7 +235,7 @@ string ExpressionIfElse::toString(int indent) {
//
// ExpressionVar
ExpressionVar::ExpressionVar(string name):
Expression(ExpressionKind::VAR, ValueType::VOID), name(name) {
Expression(ExpressionKind::VAR, ValueType::NONE), name(name) {
}
string ExpressionVar::getName() {
@@ -249,7 +249,7 @@ string ExpressionVar::toString(int indent) {
//
// ExpressionInvalid
ExpressionInvalid::ExpressionInvalid(shared_ptr<Token> token):
Expression(ExpressionKind::INVALID, ValueType::VOID), token(token) {
Expression(ExpressionKind::INVALID, ValueType::NONE), token(token) {
}
shared_ptr<Token> ExpressionInvalid::getToken() {

View File

@@ -112,6 +112,10 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
token = match(TokenKind::COMMA, ",", false);
if (token != nullptr)
return token;
token = match(TokenKind::COLON, ":", false);
if (token != nullptr)
return token;
@@ -191,6 +195,7 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
// literal
token = match(TokenKind::BOOL, "true", true);
if (token != nullptr)
return token;
@@ -199,7 +204,6 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
// literal
token = matchReal();
if (token != nullptr)
return token;
@@ -208,11 +212,20 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
// identifier
token = matchType();
// type
token = match(TokenKind::TYPE, "bool", true);
if (token != nullptr)
return token;
token = match(TokenKind::TYPE, "sint32", true);
if (token != nullptr)
return token;
token = match(TokenKind::TYPE, "real32", true);
if (token != nullptr)
return token;
// identifier
token = matchIdentifier();
if (token != nullptr)
return token;
@@ -280,30 +293,6 @@ shared_ptr<Token> Lexer::matchReal() {
return token;
}
shared_ptr<Token> Lexer::matchType() {
bool isVarDec = tokens.size() >= 2 &&
tokens.at(tokens.size() - 1)->getKind() == TokenKind::COLON &&
tokens.at(tokens.size() - 2)->getKind() == TokenKind::IDENTIFIER;
bool isFunDec = tokens.size() >= 1 &&
tokens.at(tokens.size() - 1)->getKind() == TokenKind::RIGHT_ARROW;
if (!isVarDec && !isFunDec)
return nullptr;
int nextIndex = currentIndex;
while (nextIndex < source.length() && isIdentifier(nextIndex))
nextIndex++;
if (nextIndex == currentIndex || !isSeparator(nextIndex))
return nullptr;
string lexme = source.substr(currentIndex, nextIndex - currentIndex);
shared_ptr<Token> token = make_shared<Token>(TokenKind::TYPE, lexme, currentLine, currentColumn);
advanceWithToken(token);
return token;
}
shared_ptr<Token> Lexer::matchIdentifier() {
int nextIndex = currentIndex;
@@ -365,6 +354,7 @@ bool Lexer::isSeparator(int index) {
case '>':
case '(':
case ')':
case ',':
case ':':
case ';':
case ' ':

View File

@@ -20,7 +20,7 @@ private:
shared_ptr<Token> match(TokenKind kind, string lexme, bool needsSeparator);
shared_ptr<Token> matchInteger();
shared_ptr<Token> matchReal();
shared_ptr<Token> matchType();
//shared_ptr<Token> matchType();
shared_ptr<Token> matchIdentifier();
shared_ptr<Token> matchEnd();
shared_ptr<Token> matchInvalid();

View File

@@ -97,7 +97,7 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr<Expression> expression
llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expression) {
switch (expression->getValueType()) {
case ValueType::VOID:
case ValueType::NONE:
return llvm::UndefValue::get(typeVoid);
case ValueType::BOOL:
return llvm::ConstantInt::get(typeBool, expression->getBoolValue(), true);
@@ -257,7 +257,7 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVar> expression) {
llvm::Type *ModuleBuilder::typeForValueType(ValueType valueType) {
switch (valueType) {
case ValueType::VOID:
case ValueType::NONE:
return typeVoid;
case ValueType::BOOL:
return typeBool;

View File

@@ -45,32 +45,51 @@ shared_ptr<Statement> Parser::nextStatement() {
}
shared_ptr<Statement> Parser::matchStatementFunctionDeclaration() {
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::COLON, TokenKind::FUNCTION}, true, false))
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::FUNCTION}, true, false))
return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex);
currentIndex++;
currentIndex++; // skip colon
currentIndex++; // skip fun
// Return type
ValueType returnType = ValueType::VOID;
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
shared_ptr<Token> valueTypeToken = tokens.at(currentIndex);
if (valueTypeToken->getLexme().compare("bool") == 0)
returnType = ValueType::BOOL;
else if (valueTypeToken->getLexme().compare("sint32") == 0)
returnType = ValueType::SINT32;
else if (valueTypeToken->getLexme().compare("real32") == 0)
returnType = ValueType::REAL32;
else
return matchStatementInvalid("Expected return type");
currentIndex++; // type
// Get arguments
vector<pair<string, ValueType>> arguments;
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false))
return matchStatementInvalid("Expected function argument");
shared_ptr<Token> identifierToken = tokens.at(currentIndex);
currentIndex++; // identifier
shared_ptr<Token> typeToken = tokens.at(currentIndex);
currentIndex++; // type
optional<ValueType> argumentType = valueTypeForToken(typeToken);
if (!argumentType)
return matchStatementInvalid("Invalid argument type");
arguments.push_back(pair<string, ValueType>(identifierToken->getLexme(), *argumentType));
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
}
// consume optional new line
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
// Return type
ValueType returnType = ValueType::NONE;
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
shared_ptr<Token> typeToken = tokens.at(currentIndex);
optional<ValueType> type = valueTypeForToken(typeToken);
if (!type)
return matchStatementInvalid("Expected return type");
returnType = *type;
currentIndex++; // type
// consume new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line after function declaration");
}
currentIndex++; // new line
shared_ptr<Statement> statementBlock = matchStatementBlock({TokenKind::SEMICOLON}, true);
if (statementBlock == nullptr)
return matchStatementInvalid();
@@ -80,7 +99,7 @@ shared_ptr<Statement> Parser::matchStatementFunctionDeclaration() {
if(!tryMatchingTokenKinds({TokenKind::NEW_LINE}, false, true))
return matchStatementInvalid("Expected a new line after a function declaration");
return make_shared<StatementFunctionDeclaration>(identifierToken->getLexme(), returnType, dynamic_pointer_cast<StatementBlock>(statementBlock));
return make_shared<StatementFunctionDeclaration>(identifierToken->getLexme(), arguments, returnType, dynamic_pointer_cast<StatementBlock>(statementBlock));
}
shared_ptr<Statement> Parser::matchStatementVarDeclaration() {
@@ -94,7 +113,7 @@ shared_ptr<Statement> Parser::matchStatementVarDeclaration() {
ValueType valueType;
if (valueTypeToken->getLexme().compare("bool") == 0)
valueType = ValueType::BOOL;
valueType = ValueType::BOOL;
else if (valueTypeToken->getLexme().compare("sint32") == 0)
valueType = ValueType::SINT32;
else if (valueTypeToken->getLexme().compare("real32") == 0)
@@ -395,3 +414,17 @@ bool Parser::tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll,
return false;
}
}
optional<ValueType> Parser::valueTypeForToken(shared_ptr<Token> token) {
if (token->getKind() != TokenKind::TYPE)
return {};
if (token->getLexme().compare("bool") == 0)
return ValueType::BOOL;
else if (token->getLexme().compare("sint32") == 0)
return ValueType::SINT32;
else if (token->getLexme().compare("real32") == 0)
return ValueType::REAL32;
return {};
}

View File

@@ -37,6 +37,7 @@ private:
shared_ptr<ExpressionInvalid> matchExpressionInvalid();
bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance);
optional<ValueType> valueTypeForToken(shared_ptr<Token> token);
public:
Parser(vector<shared_ptr<Token>> tokens);

View File

@@ -2,7 +2,7 @@
string valueTypeToString(ValueType valueType) {
switch (valueType) {
case ValueType::VOID:
case ValueType::NONE:
return "NONE";
case ValueType::BOOL:
return "BOOL";
@@ -32,14 +32,18 @@ string Statement::toString(int indent) {
//
// StatementFunctionDeclaration
StatementFunctionDeclaration::StatementFunctionDeclaration(string name, ValueType returnValueType, shared_ptr<StatementBlock> statementBlock):
Statement(StatementKind::FUNCTION_DECLARATION), name(name), returnValueType(returnValueType), statementBlock(statementBlock) {
StatementFunctionDeclaration::StatementFunctionDeclaration(string name, vector<pair<string, ValueType>> arguments, ValueType returnValueType, shared_ptr<StatementBlock> statementBlock):
Statement(StatementKind::FUNCTION_DECLARATION), name(name), arguments(arguments), returnValueType(returnValueType), statementBlock(statementBlock) {
}
string StatementFunctionDeclaration::getName() {
return name;
}
vector<pair<string, ValueType>> StatementFunctionDeclaration::getArguments() {
return arguments;
}
ValueType StatementFunctionDeclaration::getReturnValueType() {
return returnValueType;
}

View File

@@ -34,12 +34,14 @@ public:
class StatementFunctionDeclaration: public Statement {
private:
string name;
vector<pair<string, ValueType>> arguments;
ValueType returnValueType;
shared_ptr<StatementBlock> statementBlock;
public:
StatementFunctionDeclaration(string name, ValueType returnValueType, shared_ptr<StatementBlock> statementBlock);
StatementFunctionDeclaration(string name, vector<pair<string, ValueType>> arguments, ValueType returnValueType, shared_ptr<StatementBlock> statementBlock);
string getName();
vector<pair<string, ValueType>> getArguments();
ValueType getReturnValueType();
shared_ptr<StatementBlock> getStatementBlock();
string toString(int indent) override;

View File

@@ -104,6 +104,8 @@ string Token::toString() {
return "(";
case TokenKind::RIGHT_PAREN:
return ")";
case TokenKind::COMMA:
return ",";
case TokenKind::COLON:
return ":";
case TokenKind::SEMICOLON:

View File

@@ -17,6 +17,7 @@ enum class TokenKind {
LEFT_PAREN,
RIGHT_PAREN,
COMMA,
COLON,
SEMICOLON,
QUESTION,
@@ -58,7 +59,7 @@ enum class StatementKind {
};
enum class ValueType {
VOID,
NONE,
BOOL,
SINT32,
REAL32