feat: 添加“while 语句”支持,并对解析器进行重构以处理控制流相关内容
- 引入了 WhileStmt 结构来表示 while 循环语句。 - 在解析器中实现了对 while 语句的解析逻辑。 - 在分析器中为 while 语句添加了语义分析。 - 重构了现有的解析器方法,以利用 StateProtector 进行状态管理。 - 更新了对各种表达式和语句的错误处理。 - 移除了未使用的终止符管理方法,并简化了表达式解析。 - 将 FigLSPServer.cpp 重命名为 LSPServer.cpp,并调整了构建配置。 - 增强了重复声明和类型错误的错误报告。 - 在多个文件中改进了代码格式和一致性。
This commit is contained in:
@@ -11,14 +11,16 @@ namespace Fig
|
||||
{
|
||||
Result<LiteralExpr *, Error> Parser::parseLiteralExpr() // 当前token为literal时调用
|
||||
{
|
||||
state = State::ParsingLiteralExpr;
|
||||
StateProtector p(this, {State::ParsingLiteralExpr});
|
||||
|
||||
const Token &literal_token = consumeToken();
|
||||
LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token));
|
||||
return node;
|
||||
}
|
||||
Result<IdentiExpr *, Error> Parser::parseIdentiExpr() // 当前token为Identifier调用
|
||||
{
|
||||
state = State::ParsingIdentiExpr;
|
||||
StateProtector p(this, {State::ParsingIdentiExpr});
|
||||
|
||||
const Token &identifier = consumeToken();
|
||||
IdentiExpr *node = new IdentiExpr(
|
||||
srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier));
|
||||
@@ -27,7 +29,8 @@ namespace Fig
|
||||
|
||||
Result<InfixExpr *, Error> Parser::parseInfixExpr(Expr *lhs) // 当前token为 op
|
||||
{
|
||||
state = State::ParsingInfixExpr;
|
||||
StateProtector p(this, {State::ParsingInfixExpr});
|
||||
|
||||
const Token &op_token = consumeToken();
|
||||
BinaryOperator op = TokenToBinaryOp(op_token);
|
||||
BindingPower rbp = GetBinaryOpRBp(op);
|
||||
@@ -45,7 +48,8 @@ namespace Fig
|
||||
|
||||
Result<PrefixExpr *, Error> Parser::parsePrefixExpr() // 当前token为op
|
||||
{
|
||||
state = State::ParsingPrefixExpr;
|
||||
StateProtector p(this, {State::ParsingPrefixExpr});
|
||||
|
||||
const Token &op_token = consumeToken();
|
||||
UnaryOperator op = TokenToUnaryOp(op_token);
|
||||
|
||||
@@ -64,7 +68,8 @@ namespace Fig
|
||||
Result<IndexExpr *, Error> Parser::parseIndexExpr(
|
||||
Expr *base) // 由 parseExpression调用, 当前token为 `[`
|
||||
{
|
||||
state = State::ParsingIndexExpr;
|
||||
StateProtector p(this, {State::ParsingIndexExpr});
|
||||
|
||||
const Token &lbracket_token = consumeToken(); // consume `[`
|
||||
const auto &index_result = parseExpression();
|
||||
|
||||
@@ -89,7 +94,8 @@ namespace Fig
|
||||
Result<CallExpr *, Error> Parser::parseCallExpr(
|
||||
Expr *callee) // 由 parseExpression调用, 当前token为 `(`
|
||||
{
|
||||
state = State::ParsingCallExpr;
|
||||
StateProtector p(this, {State::ParsingCallExpr});
|
||||
|
||||
const Token &lparen_token = consumeToken(); // consume `(`
|
||||
|
||||
FnCallArgs callArgs;
|
||||
@@ -137,52 +143,8 @@ namespace Fig
|
||||
return new CallExpr(callee, callArgs);
|
||||
}
|
||||
|
||||
const std::unordered_set<TokenType> &Parser::getBaseTerminators()
|
||||
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp)
|
||||
{
|
||||
static const std::unordered_set<TokenType> baseTerminators = {TokenType::Semicolon,
|
||||
TokenType::RightParen,
|
||||
TokenType::RightBracket,
|
||||
TokenType::RightBrace,
|
||||
TokenType::Comma,
|
||||
TokenType::EndOfFile};
|
||||
return baseTerminators;
|
||||
}
|
||||
|
||||
std::unordered_set<TokenType> &Parser::getTerminators()
|
||||
{
|
||||
/*
|
||||
|
||||
Syntax terminators:
|
||||
; ) ] } , EOF
|
||||
*/
|
||||
|
||||
static std::unordered_set<TokenType> terminators(getBaseTerminators());
|
||||
return terminators;
|
||||
}
|
||||
|
||||
void Parser::resetTermintors()
|
||||
{
|
||||
getTerminators() = getBaseTerminators();
|
||||
}
|
||||
|
||||
bool Parser::shouldTerminate()
|
||||
{
|
||||
const Token &token = currentToken();
|
||||
const auto &terminators = getTerminators();
|
||||
return terminators.contains(token.type);
|
||||
}
|
||||
|
||||
Result<Expr *, Error> Parser::parseExpression(BindingPower rbp, TokenType stop, TokenType stop2)
|
||||
{
|
||||
if (!getTerminators().contains(stop))
|
||||
{
|
||||
getTerminators().insert(stop);
|
||||
}
|
||||
if (!getTerminators().contains(stop2))
|
||||
{
|
||||
getTerminators().insert(stop2);
|
||||
}
|
||||
|
||||
Expr *lhs = nullptr;
|
||||
Token token = currentToken();
|
||||
|
||||
@@ -191,7 +153,6 @@ namespace Fig
|
||||
const auto &lhs_result = parseIdentiExpr();
|
||||
if (!lhs_result)
|
||||
{
|
||||
resetTermintors();
|
||||
return std::unexpected(lhs_result.error());
|
||||
}
|
||||
lhs = *lhs_result;
|
||||
@@ -201,7 +162,6 @@ namespace Fig
|
||||
const auto &lhs_result = parseLiteralExpr();
|
||||
if (!lhs_result)
|
||||
{
|
||||
resetTermintors();
|
||||
return std::unexpected(lhs_result.error());
|
||||
}
|
||||
lhs = *lhs_result;
|
||||
@@ -211,7 +171,6 @@ namespace Fig
|
||||
const auto &lhs_result = parsePrefixExpr();
|
||||
if (!lhs_result)
|
||||
{
|
||||
resetTermintors();
|
||||
return std::unexpected(lhs_result.error());
|
||||
}
|
||||
lhs = *lhs_result;
|
||||
@@ -222,7 +181,6 @@ namespace Fig
|
||||
const auto &expr_result = parseExpression(0);
|
||||
if (!expr_result)
|
||||
{
|
||||
resetTermintors();
|
||||
return expr_result;
|
||||
}
|
||||
const Token &rparen_token = consumeToken(); // consume `)`
|
||||
@@ -238,7 +196,6 @@ namespace Fig
|
||||
|
||||
if (!lhs)
|
||||
{
|
||||
resetTermintors();
|
||||
return std::unexpected(Error(ErrorType::ExpectedExpression,
|
||||
"expected expression",
|
||||
"insert expressions",
|
||||
@@ -252,10 +209,6 @@ namespace Fig
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (token.type == stop || token.type == stop2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsTokenOp(token.type /* isBinary = true */)) // 是否为二元运算符
|
||||
{
|
||||
@@ -268,7 +221,7 @@ namespace Fig
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &result = parseInfixExpr(lhs);
|
||||
auto result = parseInfixExpr(lhs);
|
||||
if (!result)
|
||||
{
|
||||
resetTermintors();
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
@date 2026-02-14
|
||||
*/
|
||||
|
||||
|
||||
#include <Parser/Parser.hpp>
|
||||
|
||||
namespace Fig
|
||||
@@ -15,7 +14,7 @@ namespace Fig
|
||||
Program *program = new Program;
|
||||
while (!isEOF)
|
||||
{
|
||||
const auto &result = parseStatement();
|
||||
auto result = parseStatement();
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
@@ -29,4 +28,4 @@ namespace Fig
|
||||
}
|
||||
return program;
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -41,7 +41,7 @@ namespace Fig
|
||||
{
|
||||
return buffer[++index];
|
||||
}
|
||||
const auto &result = lexer.NextToken();
|
||||
auto result = lexer.NextToken();
|
||||
if (!result)
|
||||
{
|
||||
ReportError(result.error(), srcManager);
|
||||
@@ -82,7 +82,7 @@ namespace Fig
|
||||
size_t peekIndex = index + lookahead;
|
||||
while (peekIndex >= buffer.size() && !isEOF)
|
||||
{
|
||||
const auto &result = lexer.NextToken();
|
||||
auto result = lexer.NextToken();
|
||||
if (!result)
|
||||
{
|
||||
ReportError(result.error(), srcManager);
|
||||
@@ -121,51 +121,146 @@ namespace Fig
|
||||
return false;
|
||||
}
|
||||
|
||||
inline Error makeUnexpectTokenError(const String &stmtType, const String &expect, const Token &tokenGot, std::source_location loc = std::source_location::current())
|
||||
inline Error makeUnexpectTokenError(const String &stmtType,
|
||||
const String &expect,
|
||||
const Token &tokenGot,
|
||||
std::source_location loc = std::source_location::current())
|
||||
{
|
||||
return Error(
|
||||
ErrorType::SyntaxError,
|
||||
std::format("expect '{}' in {}, got `{}`", expect, stmtType, magic_enum::enum_name(tokenGot.type)),
|
||||
return Error(ErrorType::SyntaxError,
|
||||
std::format("expect '{}' in {}, got `{}`",
|
||||
expect,
|
||||
stmtType,
|
||||
magic_enum::enum_name(tokenGot.type)),
|
||||
"none",
|
||||
makeSourceLocation(tokenGot),
|
||||
loc
|
||||
);
|
||||
loc);
|
||||
}
|
||||
|
||||
inline Error makeExpectSemicolonError(std::source_location loc = std::source_location::current())
|
||||
inline Error makeExpectSemicolonError(
|
||||
std::source_location loc = std::source_location::current())
|
||||
{
|
||||
return Error(
|
||||
ErrorType::SyntaxError,
|
||||
return Error(ErrorType::SyntaxError,
|
||||
"expect ';' after statement",
|
||||
"insert ';'",
|
||||
makeSourceLocation(currentToken()),
|
||||
loc
|
||||
);
|
||||
loc);
|
||||
}
|
||||
|
||||
public:
|
||||
enum class State : std::uint8_t
|
||||
struct State
|
||||
{
|
||||
Standby,
|
||||
enum StateType : std::uint8_t
|
||||
{
|
||||
Standby,
|
||||
|
||||
ParsingLiteralExpr,
|
||||
ParsingIdentiExpr,
|
||||
ParsingLiteralExpr,
|
||||
ParsingIdentiExpr,
|
||||
|
||||
ParsingInfixExpr,
|
||||
ParsingPrefixExpr,
|
||||
ParsingInfixExpr,
|
||||
ParsingPrefixExpr,
|
||||
|
||||
ParsingIndexExpr,
|
||||
ParsingCallExpr,
|
||||
ParsingIndexExpr,
|
||||
ParsingCallExpr,
|
||||
|
||||
ParsingVarDecl,
|
||||
ParsingIf,
|
||||
ParsingVarDecl,
|
||||
ParsingIf,
|
||||
ParsingWhile,
|
||||
|
||||
} state;
|
||||
} type = StateType::Standby;
|
||||
std::unordered_set<TokenType> stopAt = {};
|
||||
};
|
||||
|
||||
private:
|
||||
const std::unordered_set<TokenType> &getBaseTerminators()
|
||||
{
|
||||
static const std::unordered_set<TokenType> baseTerminators = {TokenType::Semicolon,
|
||||
TokenType::RightParen,
|
||||
TokenType::RightBracket,
|
||||
TokenType::RightBrace,
|
||||
TokenType::Comma,
|
||||
TokenType::EndOfFile};
|
||||
return baseTerminators;
|
||||
}
|
||||
|
||||
std::unordered_set<TokenType> &getTerminators() // 返回固定的终止符
|
||||
{
|
||||
/*
|
||||
Syntax terminators:
|
||||
; ) ] } , EOF
|
||||
*/
|
||||
|
||||
static std::unordered_set<TokenType> terminators(getBaseTerminators());
|
||||
return terminators;
|
||||
}
|
||||
|
||||
void resetTermintors()
|
||||
{
|
||||
getTerminators() = getBaseTerminators();
|
||||
}
|
||||
bool shouldTerminate() // 判断是否终结
|
||||
{
|
||||
const Token &token = currentToken();
|
||||
const auto &terminators = getTerminators();
|
||||
|
||||
if (terminators.contains(token.type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for (auto it = stateStack.rbegin(); it < stateStack.rend(); ++it)
|
||||
{
|
||||
if (it->stopAt.contains(token.type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DynArray<State> stateStack;
|
||||
|
||||
State ¤tState()
|
||||
{
|
||||
return stateStack.back();
|
||||
}
|
||||
|
||||
void pushState(State _state)
|
||||
{
|
||||
stateStack.push_back(std::move(_state));
|
||||
}
|
||||
|
||||
void popState()
|
||||
{
|
||||
if (!stateStack.empty())
|
||||
{
|
||||
stateStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
class StateProtector
|
||||
{
|
||||
Parser *parser;
|
||||
|
||||
public:
|
||||
StateProtector(Parser *p, const State &newState) : parser(p)
|
||||
{
|
||||
parser->pushState(newState);
|
||||
}
|
||||
|
||||
~StateProtector()
|
||||
{
|
||||
parser->popState();
|
||||
}
|
||||
|
||||
// 禁止拷贝
|
||||
StateProtector(const StateProtector &) = delete;
|
||||
StateProtector &operator=(const StateProtector &) = delete;
|
||||
};
|
||||
|
||||
public:
|
||||
Parser(Lexer &_lexer, SourceManager &_srcManager, String _fileName) :
|
||||
lexer(_lexer), srcManager(_srcManager), fileName(std::move(_fileName))
|
||||
{
|
||||
state = State::Standby;
|
||||
pushState(State());
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -175,33 +270,33 @@ namespace Fig
|
||||
return SourceLocation(SourcePosition(line, column, tok.length),
|
||||
fileName,
|
||||
"[internal parser]",
|
||||
magic_enum::enum_name(state).data());
|
||||
magic_enum::enum_name(currentState().type).data());
|
||||
}
|
||||
|
||||
/* Expressions */
|
||||
Result<LiteralExpr *, Error> parseLiteralExpr(); // 当前token为literal时调用
|
||||
Result<IdentiExpr *, Error> parseIdentiExpr(); // 当前token为Identifier调用
|
||||
|
||||
Result<InfixExpr *, Error> parseInfixExpr(Expr *); // 由 parseExpression递归调用, 当前token为op
|
||||
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
|
||||
Result<InfixExpr *, Error> parseInfixExpr(
|
||||
Expr *); // 由 parseExpression递归调用, 当前token为op
|
||||
Result<PrefixExpr *, Error> parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op
|
||||
|
||||
Result<IndexExpr *, Error> parseIndexExpr(Expr *); // 由 parseExpression调用, 当前token为 `[`
|
||||
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
|
||||
Result<IndexExpr *, Error> parseIndexExpr(
|
||||
Expr *); // 由 parseExpression调用, 当前token为 `[`
|
||||
Result<CallExpr *, Error> parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(`
|
||||
|
||||
const std::unordered_set<TokenType> &getBaseTerminators();
|
||||
std::unordered_set<TokenType> &getTerminators(); // 返回固定的终止符
|
||||
void resetTermintors();
|
||||
bool shouldTerminate(); // 判断是否终结
|
||||
|
||||
Result<Expr *, Error> parseExpression(BindingPower = 0, TokenType stop = TokenType::Semicolon, TokenType stop2 = TokenType::Semicolon);
|
||||
Result<Expr *, Error> parseExpression(BindingPower = 0);
|
||||
|
||||
/* Statements */
|
||||
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
|
||||
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
|
||||
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token is if
|
||||
Result<Stmt *, Error> parseStatement();
|
||||
Result<BlockStmt *, Error> parseBlockStmt(); // 当前token为 {
|
||||
Result<VarDecl *, Error> parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var
|
||||
Result<IfStmt *, Error> parseIfStmt(); // 由 parseStatement调用, 当前token为 if
|
||||
Result<WhileStmt *, Error> parseWhileStmt(); // 由 parseStatement调用, 当前token为 while
|
||||
Result<Stmt *, Error> parseStatement();
|
||||
|
||||
public:
|
||||
Result<Program *, Error> Parse();
|
||||
};
|
||||
|
||||
#define SET_STOP_AT(...) currentState().stopAt = {__VA_ARGS__};
|
||||
}; // namespace Fig
|
||||
@@ -16,9 +16,9 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
Lexer lexer(source, fileName);
|
||||
Lexer lexer(source, fileName);
|
||||
Parser parser(lexer, srcManager, fileName);
|
||||
const auto &result = parser.Parse();
|
||||
auto result = parser.Parse();
|
||||
if (!result)
|
||||
{
|
||||
ReportError(result.error(), srcManager);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user