From b85f552ae29ffcd136690b66450271f90c97cd6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Grodzi=C5=84ski?= Date: Thu, 19 Jun 2025 17:23:27 +0900 Subject: [PATCH] Parse extern function --- src/Lexer.cpp | 5 +++++ src/Lexer.h | 1 - src/Parser.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++- src/Parser.h | 3 +++ src/Statement.cpp | 29 ++++++++++++++++++++++++ src/Statement.h | 16 ++++++++++++++ src/Token.cpp | 3 +++ src/Types.h | 3 +++ 8 files changed, 114 insertions(+), 2 deletions(-) diff --git a/src/Lexer.cpp b/src/Lexer.cpp index 787f5d3..c54cda7 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -230,6 +230,11 @@ shared_ptr 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) diff --git a/src/Lexer.h b/src/Lexer.h index 08bfa2d..0d756a8 100644 --- a/src/Lexer.h +++ b/src/Lexer.h @@ -20,7 +20,6 @@ private: shared_ptr match(TokenKind kind, string lexme, bool needsSeparator); shared_ptr matchInteger(); shared_ptr matchReal(); - //shared_ptr matchType(); shared_ptr matchIdentifier(); shared_ptr matchEnd(); shared_ptr matchInvalid(); diff --git a/src/Parser.cpp b/src/Parser.cpp index 30fc57b..31bed5a 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -41,7 +41,11 @@ shared_ptr Parser::nextStatement() { if (statement != nullptr) return statement; - return matchStatementInvalid(); + statement = matchStatementMetaExternFunction(); + if (statement != nullptr) + return statement; + + return matchStatementInvalid("Unexpected token"); } shared_ptr Parser::matchStatementFunctionDeclaration() { @@ -188,6 +192,56 @@ shared_ptr Parser::matchStatementExpression() { return make_shared(expression); } +shared_ptr Parser::matchStatementMetaExternFunction() { + if (!tryMatchingTokenKinds({TokenKind::M_EXTERN, TokenKind::IDENTIFIER, TokenKind::FUNCTION}, true, false)) + return nullptr; + + currentIndex++; // skip meta + shared_ptr identifierToken = tokens.at(currentIndex); + currentIndex++; + currentIndex++; // skip fun + + // Get arguments + vector> 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 identifierToken = tokens.at(currentIndex); + currentIndex++; // identifier + shared_ptr typeToken = tokens.at(currentIndex); + currentIndex++; // type + optional argumentType = valueTypeForToken(typeToken); + if (!argumentType) + return matchStatementInvalid("Invalid argument type"); + + arguments.push_back(pair(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 typeToken = tokens.at(currentIndex); + optional 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(identifierToken->getLexme(), arguments, returnType); +} + shared_ptr Parser::matchStatementInvalid(string message) { return make_shared(tokens.at(currentIndex), message); } diff --git a/src/Parser.h b/src/Parser.h index ee5eb38..d3bd810 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -20,6 +20,9 @@ private: shared_ptr matchStatementBlock(vector terminalTokenKinds, bool shouldConsumeTerminal); shared_ptr matchStatementReturn(); shared_ptr matchStatementExpression(); + + shared_ptr matchStatementMetaExternFunction(); + shared_ptr matchStatementInvalid(string message = ""); shared_ptr nextExpression(); diff --git a/src/Statement.cpp b/src/Statement.cpp index e409e17..177a7ef 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -176,6 +176,35 @@ string StatementExpression::toString(int indent) { return value; } +// +// Statement @ Function +StatementMetaExternFunction::StatementMetaExternFunction(string name, vector> arguments, ValueType returnValueType): +Statement(StatementKind::META_EXTERN_FUNCTION), name(name), arguments(arguments), returnValueType(returnValueType) { +} + +string StatementMetaExternFunction::getName() { + return name; +} + +vector> StatementMetaExternFunction::getArguments() { + return arguments; +} + +ValueType StatementMetaExternFunction::getReturnValueType() { + return returnValueType; +} + +string StatementMetaExternFunction::toString(int indent) { + string value; + for (int ind=0; ind token, string message): diff --git a/src/Statement.h b/src/Statement.h index 2e23bd8..249486d 100644 --- a/src/Statement.h +++ b/src/Statement.h @@ -101,6 +101,22 @@ public: string toString(int indent) override; }; +// +// Statement @ Extern Function +class StatementMetaExternFunction: public Statement { +private: + string name; + vector> arguments; + ValueType returnValueType; + +public: + StatementMetaExternFunction(string name, vector> arguments, ValueType returnValueType); + string getName(); + vector> getArguments(); + ValueType getReturnValueType(); + string toString(int indent) override; +}; + // // StatementInvalid class StatementInvalid: public Statement { diff --git a/src/Token.cpp b/src/Token.cpp index fb1e6a7..5c6700b 100644 --- a/src/Token.cpp +++ b/src/Token.cpp @@ -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: diff --git a/src/Types.h b/src/Types.h index 547efdf..6291e2f 100644 --- a/src/Types.h +++ b/src/Types.h @@ -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 };