Parse extern function

This commit is contained in:
Rafał Grodziński
2025-06-19 17:23:27 +09:00
parent b4775852bf
commit b85f552ae2
8 changed files with 114 additions and 2 deletions

View File

@@ -230,6 +230,11 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
// meta
token = match(TokenKind::M_EXTERN, "@extern", true);
if (token != nullptr)
return token;
// new line
token = match(TokenKind::NEW_LINE, "\n", false);
if (token != nullptr)

View File

@@ -20,7 +20,6 @@ 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> matchIdentifier();
shared_ptr<Token> matchEnd();
shared_ptr<Token> matchInvalid();

View File

@@ -41,7 +41,11 @@ shared_ptr<Statement> Parser::nextStatement() {
if (statement != nullptr)
return statement;
return matchStatementInvalid();
statement = matchStatementMetaExternFunction();
if (statement != nullptr)
return statement;
return matchStatementInvalid("Unexpected token");
}
shared_ptr<Statement> Parser::matchStatementFunctionDeclaration() {
@@ -188,6 +192,56 @@ shared_ptr<Statement> Parser::matchStatementExpression() {
return make_shared<StatementExpression>(expression);
}
shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
if (!tryMatchingTokenKinds({TokenKind::M_EXTERN, TokenKind::IDENTIFIER, TokenKind::FUNCTION}, true, false))
return nullptr;
currentIndex++; // skip meta
shared_ptr<Token> identifierToken = tokens.at(currentIndex);
currentIndex++;
currentIndex++; // skip fun
// 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");
}
return make_shared<StatementMetaExternFunction>(identifierToken->getLexme(), arguments, returnType);
}
shared_ptr<StatementInvalid> Parser::matchStatementInvalid(string message) {
return make_shared<StatementInvalid>(tokens.at(currentIndex), message);
}

View File

@@ -20,6 +20,9 @@ private:
shared_ptr<Statement> matchStatementBlock(vector<TokenKind> terminalTokenKinds, bool shouldConsumeTerminal);
shared_ptr<Statement> matchStatementReturn();
shared_ptr<Statement> matchStatementExpression();
shared_ptr<Statement> matchStatementMetaExternFunction();
shared_ptr<StatementInvalid> matchStatementInvalid(string message = "");
shared_ptr<Expression> nextExpression();

View File

@@ -176,6 +176,35 @@ string StatementExpression::toString(int indent) {
return value;
}
//
// Statement @ Function
StatementMetaExternFunction::StatementMetaExternFunction(string name, vector<pair<string, ValueType>> arguments, ValueType returnValueType):
Statement(StatementKind::META_EXTERN_FUNCTION), name(name), arguments(arguments), returnValueType(returnValueType) {
}
string StatementMetaExternFunction::getName() {
return name;
}
vector<pair<string, ValueType>> StatementMetaExternFunction::getArguments() {
return arguments;
}
ValueType StatementMetaExternFunction::getReturnValueType() {
return returnValueType;
}
string StatementMetaExternFunction::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += "EXTERN_FUN(";
value += name + ", ";
value += valueTypeToString(returnValueType);
value += ")\n";
return value;
}
//
// StatementInvalid
StatementInvalid::StatementInvalid(shared_ptr<Token> token, string message):

View File

@@ -101,6 +101,22 @@ public:
string toString(int indent) override;
};
//
// Statement @ Extern Function
class StatementMetaExternFunction: public Statement {
private:
string name;
vector<pair<string, ValueType>> arguments;
ValueType returnValueType;
public:
StatementMetaExternFunction(string name, vector<pair<string, ValueType>> arguments, ValueType returnValueType);
string getName();
vector<pair<string, ValueType>> getArguments();
ValueType getReturnValueType();
string toString(int indent) override;
};
//
// StatementInvalid
class StatementInvalid: public Statement {

View File

@@ -135,6 +135,9 @@ string Token::toString() {
case TokenKind::RETURN:
return "RETURN";
case TokenKind::M_EXTERN:
return "@EXTERN";
case TokenKind::NEW_LINE:
return "";
case TokenKind::END:

View File

@@ -34,6 +34,8 @@ enum class TokenKind {
IDENTIFIER,
TYPE,
M_EXTERN,
NEW_LINE,
END,
@@ -56,6 +58,7 @@ enum class StatementKind {
BLOCK,
RETURN,
EXPRESSION,
META_EXTERN_FUNCTION,
INVALID
};