feat: 添加函数定义和类型表达式支持,重构解析器以处理新语法(函数定义)

This commit is contained in:
2026-02-26 14:41:41 +08:00
parent 12dc31a6c0
commit bb23ddf9fa
9 changed files with 376 additions and 11 deletions

View File

@@ -15,6 +15,8 @@
#include <Ast/Expr/PrefixExpr.hpp>
#include <Ast/Stmt/ExprStmt.hpp>
#include <Ast/Stmt/FnDefStmt.hpp>
#include <Ast/Stmt/IfStmt.hpp>
#include <Ast/Stmt/VarDecl.hpp>
#include <Ast/Stmt/WhileStmt.hpp>
#include <Ast/TypeExpr.hpp>

View File

@@ -38,6 +38,12 @@ namespace Fig
IfStmt, // If语句
ElseIfStmt, // ElseIf语句不准悬空平铺式else if
WhileStmt, // while语句
FnDefStmt, // func函数定义语句
/* Type Expressions */
TypeExpr, // 基类
NamedTypeExpr, // 命名类型支持namespace, std.file这样的
// 泛型等...
};
struct AstNode
{
@@ -45,7 +51,16 @@ namespace Fig
SourceLocation location;
virtual String toString() const = 0;
virtual ~AstNode(){};
virtual ~AstNode() {};
};
struct TypeExpr : public AstNode
{
TypeExpr()
{
type = AstType::TypeExpr;
}
virtual ~TypeExpr() = default;
};
struct Program;

100
src/Ast/Stmt/FnDefStmt.hpp Normal file
View File

@@ -0,0 +1,100 @@
/*!
@file src/Ast/Stmt/FnDefStmt.hpp
@brief FnDefStmt定义
@author PuqiAR (im@puqiar.top)
@date 2026-02-25
*/
#pragma once
#include <Ast/Base.hpp>
namespace Fig
{
struct Param
{
String name;
SourceLocation location;
virtual String toString() const = 0;
};
struct PosParam final : public Param
{
TypeExpr *type;
Expr *defaultValue;
PosParam() {}
PosParam(String _name, TypeExpr *_type, Expr *_defaultValue, SourceLocation _location) :
type(_type), defaultValue(_defaultValue)
{
name = std::move(_name);
location = std::move(_location);
}
virtual String toString() const override
{
return std::format(
"<Pos {}: {}{}>",
name,
(type ? type->toString() : "Any"),
(defaultValue ? " =" + defaultValue->toString() : "")
);
}
};
/*
(public) func foo([name: (type) (= default value)]) (-> return type)
{
...
}
*/
struct FnDefStmt final : public Stmt
{
String name;
DynArray<Param *> params;
TypeExpr *returnType;
BlockStmt *body;
FnDefStmt()
{
type = AstType::FnDefStmt;
}
FnDefStmt(bool _isPublic,
String _name,
DynArray<Param *> _params,
TypeExpr *_returnType,
BlockStmt *_body,
SourceLocation _location) :
name(std::move(_name)), params(std::move(_params)), returnType(_returnType), body(_body)
{
type = AstType::FnDefStmt;
isPublic = _isPublic;
location = std::move(_location);
}
virtual String toString() const override
{
String pStr;
for (const Param *p : params)
{
if (p != *params.begin())
{
pStr += ", ";
}
pStr += p->toString();
}
return std::format(
"<FnDefStmt {}{}({}) -> {} {{{}}}>",
(isPublic ? "public " : ""),
name,
pStr,
(returnType ? returnType->toString() : "Any"),
body->toString()
);
}
};
}; // namespace Fig

View File

@@ -15,7 +15,7 @@ namespace Fig
struct VarDecl final : public Stmt
{
String name;
Expr *typeSpecifier;
TypeExpr *typeSpecifier;
bool isInfer; // 是否用了 := 类型推断
Expr *initExpr;
@@ -26,7 +26,7 @@ namespace Fig
type = AstType::VarDecl;
}
VarDecl(bool _isPublic, String _name, Expr *_typeSpecifier, bool _isInfer, Expr *_initExpr, SourceLocation _location) :
VarDecl(bool _isPublic, String _name, TypeExpr *_typeSpecifier, bool _isInfer, Expr *_initExpr, SourceLocation _location) :
name(std::move(_name)),
typeSpecifier(_typeSpecifier),
isInfer(_isInfer),

36
src/Ast/TypeExpr.hpp Normal file
View File

@@ -0,0 +1,36 @@
/*!
@file src/Ast/TypeExpr.hpp
@brief TypeExpr定义
@author PuqiAR (im@puqiar.top)
@date 2026-02-25
*/
#pragma once
#include <Ast/Base.hpp>
namespace Fig
{
struct NamedTypeExpr final : public TypeExpr
{
DynArray<String> path; // {"std", "file"} etc.
NamedTypeExpr()
{
type = AstType::NamedTypeExpr;
}
NamedTypeExpr(DynArray<String> _path, SourceLocation _location) :
path(std::move(_path))
{
type = AstType::NamedTypeExpr;
location = std::move(_location);
}
virtual String toString() const override
{
return std::format("<NamedTypeExpr '{}'>", path);
}
};
};

View File

@@ -165,6 +165,9 @@ namespace Fig
ParsingVarDecl,
ParsingIf,
ParsingWhile,
ParsingFnDefStmt,
ParsingNamedTypeExpr,
} type = StateType::Standby;
std::unordered_set<TokenType> stopAt = {};
@@ -273,6 +276,12 @@ namespace Fig
magic_enum::enum_name(currentState().type).data());
}
/* TypeExpressions */
Result<NamedTypeExpr *, Error> parseNamedTypeExpr(); // 当前token为identifier
Result<TypeExpr *, Error> parseTypeExpr();
/* Expressions */
Result<LiteralExpr *, Error> parseLiteralExpr(); // 当前token为literal时调用
Result<IdentiExpr *, Error> parseIdentiExpr(); // 当前token为Identifier调用
@@ -292,6 +301,10 @@ namespace Fig
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token为 if
Result<WhileStmt *, Error> parseWhileStmt(); // 由 parseStatement调用, 当前token为 while
Result<DynArray<Param *>, Error> parseFnParams(); // 由 parseFnDefStmt或lambda调用
Result<FnDefStmt *, Error> parseFnDefStmt(bool); // 由 parseStatement调用, 当前token为 func
Result<Stmt *, Error> parseStatement();
public:

View File

@@ -49,11 +49,11 @@ namespace Fig
const String &name = srcManager.GetSub(currentToken().index, currentToken().length);
consumeToken(); // consume name
Expr *typeSpeicifer = nullptr;
TypeExpr *typeSpeicifer = nullptr;
if (match(TokenType::Colon)) // `:`
{
SET_STOP_AT(TokenType::Walrus, TokenType::Assign);
auto result = parseExpression(0);
// SET_STOP_AT(TokenType::Walrus, TokenType::Assign);
auto result = parseTypeExpr();
if (!result)
{
return std::unexpected(result.error());
@@ -295,6 +295,136 @@ namespace Fig
return whileStmt;
}
Result<DynArray<Param *>, Error> Parser::parseFnParams() // 由 parseFnDefStmt或lambda调用
{
StateProtector p(this, {State::ParsingFnDefStmt});
const Token &lpToken = consumeToken(); // consume `(`
DynArray<Param *> params;
while (true)
{
if (isEOF)
{
return std::unexpected(Error(ErrorType::SyntaxError,
"unclosed parenthese in function parameters",
"insert ')'",
makeSourceLocation(lpToken)));
}
if (match(TokenType::RightParen))
{
break;
}
const Token &nToken = consumeToken();
SourceLocation location = makeSourceLocation(nToken);
const String &name = srcManager.GetSub(nToken.index, nToken.length);
// TODO: 支持剩余参数解析...
TypeExpr *type = nullptr;
if (match(TokenType::Colon)) // :
{
auto result = parseTypeExpr();
if (!result)
{
return std::unexpected(result.error());
}
type = *result;
}
Expr *defaultValue = nullptr;
if (match(TokenType::Assign)) // =
{
SET_STOP_AT(TokenType::Comma, TokenType::RightParen, TokenType::LeftBrace); // , ) {
auto result = parseExpression();
if (!result)
{
if (type)
{
delete type;
}
return std::unexpected(result.error());
}
defaultValue = *result;
}
PosParam *posParam = new PosParam(name, type, defaultValue, location);
params.push_back(posParam);
if (match(TokenType::Comma))
{
if (!currentToken().isIdentifier())
{
return std::unexpected(makeUnexpectTokenError("fn params", "param name", currentToken()));
}
}
}
return params;
}
Result<FnDefStmt *, Error> Parser::parseFnDefStmt(
bool isPublic) // 由 parseStatement调用, 当前token为 func
{
SourceLocation location = makeSourceLocation(
consumeToken()); // 无论是否加了public, location都设置为 func token (我懒 :D)
if (!currentToken().isIdentifier())
{
return std::unexpected(
makeUnexpectTokenError("fn def stmt", "function name", currentToken()));
}
const Token &nameToken = consumeToken(); // consume name
const String &name = srcManager.GetSub(nameToken.index, nameToken.length);
if (currentToken().type != TokenType::LeftParen)
{
return std::unexpected(
makeUnexpectTokenError("fn def stmt", "lparen '('", currentToken()));
}
DynArray<Param *> params;
auto paraResult = parseFnParams();
if (!paraResult)
{
return std::unexpected(paraResult.error());
}
params = *paraResult;
TypeExpr *returnType = nullptr;
if (match(TokenType::RightArrow)) // ->
{
auto result = parseTypeExpr();
if (!result)
{
return std::unexpected(result.error());
}
returnType = *result;
}
if (currentToken().type != TokenType::LeftBrace)
{
return std::unexpected(
makeUnexpectTokenError("fn def stmt", "function body '{'", currentToken()));
}
BlockStmt *body = nullptr;
auto bodyResult = parseBlockStmt();
if (!bodyResult)
{
if (returnType)
{
delete returnType;
}
body = *bodyResult;
}
FnDefStmt *fnDef = new FnDefStmt(isPublic, name, params, returnType, body, location);
return fnDef;
}
Result<Stmt *, Error> Parser::parseStatement()
{
StateProtector p(this, {State::Standby});
@@ -306,12 +436,15 @@ namespace Fig
{
return parseVarDecl(true);
}
else
if (currentToken().type == TokenType::Function)
{
return parseFnDefStmt(true);
}
return std::unexpected(
makeUnexpectTokenError("public", "var/const/func/struct", currentToken()));
}
}
if (currentToken().type == TokenType::LeftBrace)
{
@@ -333,6 +466,11 @@ namespace Fig
return parseWhileStmt();
}
if (currentToken().type == TokenType::Function)
{
return parseFnDefStmt(false);
}
if (isEOF)
{
return nullptr;

View File

@@ -0,0 +1,56 @@
/*!
@file src/Parser/TypeExprParser.cpp
@brief 类型表达式解析器实现
@author PuqiAR (im@puqiar.top)
@date 2026-02-25
*/
#pragma once
#include <Parser/Parser.hpp>
namespace Fig
{
Result<NamedTypeExpr *, Error> Parser::parseNamedTypeExpr() // 当前token为identifier
{
StateProtector p(this, {State::ParsingNamedTypeExpr});
SourceLocation location = makeSourceLocation(currentToken());
DynArray<String> path;
while (true)
{
const Token &subPathTok = consumeToken();
const String &subPath = srcManager.GetSub(subPathTok.index, subPathTok.length);
path.push_back(subPath);
if (match(TokenType::Dot))
{
if (!currentToken().isIdentifier())
{
return std::unexpected(
makeUnexpectTokenError("named type expr", "identifier", currentToken()));
}
}
else
{
break;
}
}
NamedTypeExpr *namedTypeExpr = new NamedTypeExpr(path, location);
return namedTypeExpr;
}
Result<TypeExpr *, Error> Parser::parseTypeExpr()
{
// TODO: 泛型表达式解析
if (currentToken().isIdentifier())
{
return parseNamedTypeExpr();
}
else
{
return std::unexpected(makeUnexpectTokenError("type expr", "name/...", currentToken()));
}
}
}; // namespace Fig

View File

@@ -45,6 +45,7 @@ target("ParserTest")
add_files("src/Ast/Operator.cpp")
add_files("src/Parser/ExprParser.cpp")
add_files("src/Parser/StmtParser.cpp")
add_files("src/Parser/TypeExprParser.cpp")
add_files("src/Parser/Parser.cpp")
add_files("src/Parser/ParserTest.cpp")
@@ -62,6 +63,7 @@ target("AnalyzerTest")
add_files("src/Ast/Operator.cpp")
add_files("src/Parser/ExprParser.cpp")
add_files("src/Parser/StmtParser.cpp")
add_files("src/Parser/TypeExprParser.cpp")
add_files("src/Parser/Parser.cpp")
add_files("src/Sema/Analyzer.cpp")
@@ -76,6 +78,7 @@ target("CompilerTest")
add_files("src/Ast/Operator.cpp")
add_files("src/Parser/ExprParser.cpp")
add_files("src/Parser/StmtParser.cpp")
add_files("src/Parser/TypeExprParser.cpp")
add_files("src/Parser/Parser.cpp")
add_files("src/Object/Object.cpp")
@@ -97,6 +100,7 @@ target("LSP")
add_files("src/Ast/Operator.cpp")
add_files("src/Parser/ExprParser.cpp")
add_files("src/Parser/StmtParser.cpp")
add_files("src/Parser/TypeExprParser.cpp")
add_files("src/Parser/Parser.cpp")
add_files("src/Sema/Analyzer.cpp")
@@ -114,6 +118,7 @@ target("Fig")
add_files("src/Ast/Operator.cpp")
add_files("src/Parser/ExprParser.cpp")
add_files("src/Parser/StmtParser.cpp")
add_files("src/Parser/TypeExprParser.cpp")
add_files("src/Parser/Parser.cpp")
add_files("src/Object/Object.cpp")