feat: 添加“while 语句”支持,并对解析器进行重构以处理控制流相关内容

- 引入了 WhileStmt 结构来表示 while 循环语句。
- 在解析器中实现了对 while 语句的解析逻辑。
- 在分析器中为 while 语句添加了语义分析。
- 重构了现有的解析器方法,以利用 StateProtector 进行状态管理。
- 更新了对各种表达式和语句的错误处理。
- 移除了未使用的终止符管理方法,并简化了表达式解析。
- 将 FigLSPServer.cpp 重命名为 LSPServer.cpp,并调整了构建配置。
- 增强了重复声明和类型错误的错误报告。
- 在多个文件中改进了代码格式和一致性。
This commit is contained in:
2026-02-25 17:31:00 +08:00
parent b7bb889676
commit a0fb8cdffb
25 changed files with 670 additions and 355 deletions

View File

@@ -19,14 +19,14 @@ namespace Fig
{
return std::unexpected(Error(ErrorType::SyntaxError,
"unclosed braces in block stmt",
"insert `}`",
"insert '}'",
location));
}
if (match(TokenType::RightBrace))
{
break;
}
const auto &result = parseStatement();
auto result = parseStatement();
if (!result)
{
return std::unexpected(result.error());
@@ -38,7 +38,7 @@ namespace Fig
Result<VarDecl *, Error> Parser::parseVarDecl(
bool isPublic) // 由 parseStatement调用, 当前token为 var
{
state = State::ParsingVarDecl;
StateProtector p(this, {State::ParsingVarDecl});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `var`
@@ -52,7 +52,8 @@ namespace Fig
Expr *typeSpeicifer = nullptr;
if (match(TokenType::Colon)) // `:`
{
const auto &result = parseExpression(0, TokenType::Assign, TokenType::Walrus);
SET_STOP_AT(TokenType::Walrus, TokenType::Assign);
auto result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
@@ -61,10 +62,10 @@ namespace Fig
}
Expr *initExpr = nullptr;
bool isInfer = false;
bool isInfer = false;
if (match(TokenType::Assign))
{
const auto &result = parseExpression();
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
@@ -73,22 +74,21 @@ namespace Fig
}
else if (match(TokenType::Walrus)) // :=
{
if (typeSpeicifer) // 指定了类型同时使用 :=
if (typeSpeicifer) // 指定了类型同时使用 :=
{
return std::unexpected(Error(
ErrorType::SyntaxError,
return std::unexpected(Error(ErrorType::SyntaxError,
"used type infer but specifying the type",
"change `:=` to '='",
makeSourceLocation(prevToken()) // :=
));
));
}
const auto &result = parseExpression();
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
}
initExpr = *result;
isInfer = true; // 使用类型自动推断 :=
isInfer = true; // 使用类型自动推断 :=
}
if (!match(TokenType::Semicolon))
{
@@ -100,14 +100,16 @@ namespace Fig
Result<IfStmt *, Error> Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if
{
state = State::ParsingIf;
StateProtector p(this, {State::ParsingIf});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `if`
Expr *cond = nullptr;
if (match(TokenType::LeftParen)) // match and consume `(`
{
const Token &lpToken = prevToken();
const auto &result = parseExpression(0, TokenType::RightParen, TokenType::LeftBrace);
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
const auto &result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
@@ -124,21 +126,21 @@ namespace Fig
}
else
{
const auto &result = parseExpression(0, TokenType::LeftBrace);
SET_STOP_AT(TokenType::LeftBrace);
auto result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
}
cond = *result;
}
state = State::ParsingIf;
if (currentToken().type != TokenType::LeftBrace)
{
return std::unexpected(
makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
@@ -167,13 +169,13 @@ namespace Fig
if (match(TokenType::LeftParen)) // `(`
{
const Token &lpToken = prevToken();
const auto &result =
parseExpression(0, TokenType::RightParen, TokenType::LeftBrace);
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
const auto &result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
if (!match(TokenType::RightParen))
{
delete *result;
@@ -186,25 +188,24 @@ namespace Fig
}
else
{
const auto &result = parseExpression(0, TokenType::LeftBrace);
SET_STOP_AT(TokenType::LeftBrace);
auto result = parseExpression(0);
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
cond = *result;
cond = *result;
}
if (currentToken().type != TokenType::LeftBrace)
{
return std::unexpected(
makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
BlockStmt *consequent = *result;
ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation);
elifs.push_back(elif);
@@ -224,12 +225,11 @@ namespace Fig
return std::unexpected(
makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken()));
}
const auto &result = parseBlockStmt();
auto result = parseBlockStmt();
if (!result)
{
return std::unexpected(result.error());
}
state = State::ParsingIf;
alternate = *result;
}
}
@@ -237,9 +237,68 @@ namespace Fig
return ifStmt;
}
Result<WhileStmt *, Error> Parser::parseWhileStmt() // 由 parseStatement调用, 当前token为 while
{
StateProtector p(this, {State::ParsingWhile});
SourceLocation location = makeSourceLocation(consumeToken()); // consume `while`
Expr *cond = nullptr;
if (match(TokenType::LeftParen))
{
const Token &lpToken = prevToken();
SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace);
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
}
if (!match(TokenType::RightParen))
{
delete *result;
return std::unexpected(Error(ErrorType::SyntaxError,
"unclosed parenthese in while condition",
"insert ')'",
makeSourceLocation(lpToken)));
}
cond = *result;
}
else
{
SET_STOP_AT(TokenType::LeftBrace);
auto result = parseExpression();
if (!result)
{
return std::unexpected(result.error());
}
cond = *result;
}
if (currentToken().type != TokenType::LeftBrace)
{
delete cond;
return std::unexpected(
makeUnexpectTokenError("while stmt", "left brace '{'", currentToken()));
}
auto result = parseBlockStmt();
if (!result)
{
delete cond;
return std::unexpected(result.error());
}
BlockStmt *body = *result;
WhileStmt *whileStmt = new WhileStmt(cond, body, location);
return whileStmt;
}
Result<Stmt *, Error> Parser::parseStatement()
{
state = State::Standby;
StateProtector p(this, {State::Standby});
if (currentToken().type == TokenType::Public)
{
consumeToken(); // consume `public`
@@ -247,20 +306,38 @@ namespace Fig
{
return parseVarDecl(true);
}
else
{
return std::unexpected(
makeUnexpectTokenError("public", "var/const/func/struct", currentToken()));
}
}
if (currentToken().type == TokenType::LeftBrace)
{
return parseBlockStmt();
}
if (currentToken().type == TokenType::Variable)
{
return parseVarDecl(false);
}
if (currentToken().type == TokenType::If)
{
return parseIfStmt();
}
if (currentToken().type == TokenType::While)
{
return parseWhileStmt();
}
if (isEOF)
{
return nullptr;
}
const auto &expr_result = parseExpression();
if (!expr_result)
{