[VER] 0.3.4-alpha

[FEAT] 异常系统, try/catch/finally
This commit is contained in:
2025-12-30 17:42:41 +08:00
parent 6982f169aa
commit 9f24392034
13 changed files with 857 additions and 470 deletions

View File

@@ -1,3 +1,4 @@
#include "Ast/Statements/ErrorFlow.hpp"
#include "Ast/Statements/ImplementSt.hpp"
#include "Ast/astBase.hpp"
#include "Ast/functionParameters.hpp"
@@ -30,6 +31,7 @@ namespace Fig
{Ast::Operator::LessEqual, {8, 9}},
{Ast::Operator::Greater, {8, 9}},
{Ast::Operator::GreaterEqual, {8, 9}},
{Ast::Operator::Is, {8, 9}},
// 位运算
{Ast::Operator::BitAnd, {6, 7}},
@@ -478,6 +480,89 @@ namespace Fig
return makeAst<Ast::ImplementAst>(interfaceName, structName, methods);
}
Ast::Throw Parser::__parseThrow()
{
// entry: current is `throw`
next(); // consume `throw`
Ast::Expression exp = parseExpression(0);
expect(TokenType::Semicolon);
next(); // consume `;`
return makeAst<Ast::ThrowSt>(exp);
}
Ast::Try Parser::__parseTry()
{
// entry: current is `try`
next(); // consume `try`
/*
try
{
...
}
catch(e: IOError)
{
}
catch(e: TimeOutError)
{
}
*/
expect(TokenType::LeftBrace);
Ast::BlockStatement body = __parseBlockStatement();
std::vector<Ast::Catch> catches;
Ast::BlockStatement finallyBlock = nullptr;
while (true)
{
if (isThis(TokenType::Catch))
{
next(); // consume `catch`
expect(TokenType::LeftParen);
next(); // consume `(`
expect(TokenType::Identifier, u8"error receive var name");
FString errVarName = currentToken().getValue();
next(); // consume name
bool hasType = false;
FString errVarType;
if (isThis(TokenType::Colon)) // :
{
next();
expect(TokenType::Identifier, u8"error type");
errVarType = currentToken().getValue();
next(); // consume var type
hasType = true;
}
expect(TokenType::RightParen); //
next(); // consume `)`
expect(TokenType::LeftBrace); // {
Ast::BlockStatement catchBody = __parseBlockStatement();
if (hasType)
{
catches.push_back(Ast::Catch(errVarName, errVarType, catchBody));
}
else {
catches.push_back(Ast::Catch(errVarName, catchBody));
}
}
else if (isThis(TokenType::Finally))
{
if (finallyBlock != nullptr)
{
throw SyntaxError(u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
}
next(); // consume `finally`
expect(TokenType::LeftBrace);
finallyBlock = __parseBlockStatement();
}
else
{
break;
}
}
return makeAst<Ast::TrySt>(body, catches, finallyBlock);
}
Ast::Statement Parser::__parseStatement()
{
Ast::Statement stmt;
@@ -568,6 +653,14 @@ namespace Fig
{
stmt = __parseContinue();
}
else if (isThis(TokenType::Throw))
{
stmt = __parseThrow();
}
else if (isThis(TokenType::Try))
{
stmt = __parseTry();
}
else
{
// expression statement

View File

@@ -6,6 +6,7 @@
#include <Error/error.hpp>
#include <print>
#include <source_location>
#include <unordered_map>
#include <stack>
@@ -211,43 +212,43 @@ namespace Fig
return ptr;
}
void expectPeek(TokenType type)
void expectPeek(TokenType type, std::source_location loc = std::source_location::current())
{
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(peekToken().getType()))));
magic_enum::enum_name(peekToken().getType()))), loc);
}
}
void expect(TokenType type)
void expect(TokenType type, std::source_location loc = std::source_location::current())
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
magic_enum::enum_name(type),
magic_enum::enum_name(currentToken().getType()))));
magic_enum::enum_name(currentToken().getType()))), loc);
}
}
void expectPeek(TokenType type, FString expected)
void expectPeek(TokenType type, FString expected, std::source_location loc = std::source_location::current())
{
if (peekToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(peekToken().getType()))));
magic_enum::enum_name(peekToken().getType()))), loc);
}
}
void expect(TokenType type, FString expected)
void expect(TokenType type, FString expected, std::source_location loc = std::source_location::current())
{
if (currentToken().getType() != type)
{
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
expected.toBasicString(),
magic_enum::enum_name(currentToken().getType()))));
magic_enum::enum_name(currentToken().getType()))), loc);
}
}
@@ -316,6 +317,9 @@ namespace Fig
Ast::InterfaceDef __parseInterfaceDef(bool); // entry: current is Token::Identifier (interface name) arg(isPublic: bool)
Ast::Implement __parseImplement(); // entry: current is `impl`
Ast::Throw __parseThrow(); // entry: current is `throw`
Ast::Try __parseTry(); // entry: current is `try`
Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence);
Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence);
Ast::Expression __parseCall(Ast::Expression);