feat: 增加函数类型表达式支持,更新解析器和分析器

This commit is contained in:
2026-03-18 17:30:09 +08:00
parent e1d9812f92
commit 570a87c3cd
10 changed files with 228 additions and 35 deletions
+87 -15
View File
@@ -25,9 +25,11 @@ namespace Fig
if (match(TokenType::Dot))
{
if (!currentToken().isIdentifier())
return std::unexpected(makeUnexpectTokenError("Type", "identifier", currentToken()));
return std::unexpected(
makeUnexpectTokenError("Type", "identifier", currentToken()));
}
else break;
else
break;
}
DynArray<TypeExpr *> arguments;
@@ -36,38 +38,108 @@ namespace Fig
while (true)
{
auto result = parseTypeExpr();
if (!result) return std::unexpected(result.error());
if (!result)
return std::unexpected(result.error());
arguments.push_back(*result);
if (match(TokenType::Greater)) break; // `>`
if (match(TokenType::Greater))
break; // `>`
if (!match(TokenType::Comma))
return std::unexpected(makeUnexpectTokenError("TypeArgs", "'>' or ','", currentToken()));
return std::unexpected(
makeUnexpectTokenError("TypeArgs", "'>' or ','", currentToken()));
}
}
return arena.Allocate<NamedTypeExpr>(path, arguments, location);
}
Result<TypeExpr *, Error> Parser::parseFnTypeExpr()
{
StateProtector p(this, {State::ParsingFnTypeExpr});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `func`
if (!match(TokenType::LeftParen)) // `(`
{
return std::unexpected(
makeUnexpectTokenError("FnTypeExpr", "lparen (", currentToken()));
}
DynArray<TypeExpr *> paraTypes;
while (true)
{
auto result = parseTypeExpr();
if (!result)
{
return result;
}
paraTypes.push_back(*result);
if (match(TokenType::RightParen))
{
break;
}
else if (isEOF)
{
return std::unexpected(
makeUnexpectTokenError("FnTypeExpr", "rparen )", currentToken()));
}
if (!match(TokenType::Comma))
{
return std::unexpected(
makeUnexpectTokenError("FnTypeExpr", "comma ,", currentToken()));
}
}
TypeExpr *returnType = nullptr;
if (match(TokenType::RightArrow)) // ->
{
auto result = parseTypeExpr();
if (!result)
{
return result;
}
returnType = *result;
}
FnTypeExpr *fnTypeExpr = arena.Allocate<FnTypeExpr>(paraTypes, returnType);
return fnTypeExpr;
}
// 解析主入口: 处理 `?` 后缀
Result<TypeExpr *, Error> Parser::parseTypeExpr()
{
TypeExpr *base = nullptr;
// 目前只支持命名类型 (以后可以加函数类型 (Int)->Int)
if (currentToken().isIdentifier())
{
auto res = parseNamedTypeExpr();
if (!res) return std::unexpected(res.error());
base = *res;
auto result = parseNamedTypeExpr();
if (!result)
{
return result;
}
base = *result;
}
else return std::unexpected(makeUnexpectTokenError("TypeExpr", "name", currentToken()));
// 空安全处理: Int?? 也可以,但 Analyzer 会规范化它
while (match(TokenType::Question))
else if (currentToken().type == TokenType::Function)
{
base = arena.Allocate<NullableTypeExpr>(base, makeSourceLocation(prevToken()));
auto result = parseFnTypeExpr();
if (!result)
{
return result;
}
base = *result;
}
else
{
return std::unexpected(makeUnexpectTokenError("TypeExpr", "name", currentToken()));
}
// type (?)
if (currentToken().type == TokenType::Question) // ?
{
base = arena.Allocate<NullableTypeExpr>(base, makeSourceLocation(consumeToken())); // consume `?`
}
return base;
}
}
} // namespace Fig