feat: 添加If语句及块语句解析支持
This commit is contained in:
@@ -158,6 +158,7 @@ namespace Fig
|
||||
ParsingCallExpr,
|
||||
|
||||
ParsingVarDecl,
|
||||
ParsingIf,
|
||||
|
||||
} state;
|
||||
|
||||
@@ -193,8 +194,9 @@ namespace Fig
|
||||
Result<Expr *, Error> parseExpression(BindingPower = 0, TokenType stop = TokenType::Semicolon, TokenType stop2 = TokenType::Semicolon);
|
||||
|
||||
/* 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();
|
||||
|
||||
public:
|
||||
|
||||
@@ -9,7 +9,34 @@
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
Result<VarDecl *, Error> Parser::parseVarDecl(bool isPublic) // 由 parseStatement调用, 当前token为 var
|
||||
Result<BlockStmt *, Error> Parser::parseBlockStmt() // 当前token为 {
|
||||
{
|
||||
SourceLocation location = makeSourceLocation(consumeToken()); // consume `{`
|
||||
BlockStmt *stmt = new BlockStmt();
|
||||
while (true)
|
||||
{
|
||||
if (isEOF)
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||
"unclosed braces in block stmt",
|
||||
"insert `}`",
|
||||
location));
|
||||
}
|
||||
if (match(TokenType::RightBrace))
|
||||
{
|
||||
break;
|
||||
}
|
||||
const auto &result = parseStatement();
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
stmt->nodes.push_back(*result);
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
Result<VarDecl *, Error> Parser::parseVarDecl(
|
||||
bool isPublic) // 由 parseStatement调用, 当前token为 var
|
||||
{
|
||||
state = State::ParsingVarDecl;
|
||||
|
||||
@@ -50,8 +77,147 @@ namespace Fig
|
||||
VarDecl *varDecl = new VarDecl(isPublic, name, typeSpeicifer, initExpr, location);
|
||||
return varDecl;
|
||||
}
|
||||
|
||||
Result<IfStmt *, Error> Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if
|
||||
{
|
||||
state = 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);
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
if (!match(TokenType::RightParen))
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||
"unclosed parenthese in if condition",
|
||||
"insert `)`",
|
||||
makeSourceLocation(lpToken)));
|
||||
}
|
||||
cond = *result;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &result = parseExpression(0, TokenType::LeftBrace);
|
||||
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();
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
BlockStmt *consequent = *result;
|
||||
|
||||
DynArray<ElseIfStmt *> elifs;
|
||||
BlockStmt *alternate = nullptr;
|
||||
|
||||
while (match(TokenType::Else))
|
||||
{
|
||||
SourceLocation elseLocation = makeSourceLocation(prevToken());
|
||||
if (match(TokenType::If))
|
||||
{
|
||||
// else if
|
||||
if (alternate)
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||
"else if after else",
|
||||
"remove else if",
|
||||
elseLocation));
|
||||
}
|
||||
|
||||
Expr *cond = nullptr;
|
||||
|
||||
if (match(TokenType::LeftParen)) // `(`
|
||||
{
|
||||
const Token &lpToken = prevToken();
|
||||
const auto &result =
|
||||
parseExpression(0, TokenType::RightParen, TokenType::LeftBrace);
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
state = State::ParsingIf;
|
||||
if (!match(TokenType::RightParen))
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||
"unclosed parenthese in if condition",
|
||||
"insert `)`",
|
||||
makeSourceLocation(lpToken)));
|
||||
}
|
||||
cond = *result;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &result = parseExpression(0, TokenType::LeftBrace);
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
state = State::ParsingIf;
|
||||
cond = *result;
|
||||
}
|
||||
if (currentToken().type != TokenType::LeftBrace)
|
||||
{
|
||||
return std::unexpected(
|
||||
makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken()));
|
||||
}
|
||||
const 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// else
|
||||
if (alternate)
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::SyntaxError,
|
||||
"duplicate else in if stmt",
|
||||
"remove it",
|
||||
elseLocation));
|
||||
}
|
||||
if (currentToken().type != TokenType::LeftBrace)
|
||||
{
|
||||
return std::unexpected(
|
||||
makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken()));
|
||||
}
|
||||
const auto &result = parseBlockStmt();
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
state = State::ParsingIf;
|
||||
alternate = *result;
|
||||
}
|
||||
}
|
||||
IfStmt *ifStmt = new IfStmt(cond, consequent, elifs, alternate, location);
|
||||
return ifStmt;
|
||||
}
|
||||
|
||||
Result<Stmt *, Error> Parser::parseStatement()
|
||||
{
|
||||
state = State::Standby;
|
||||
if (currentToken().type == TokenType::Public)
|
||||
{
|
||||
consumeToken(); // consume `public`
|
||||
@@ -60,23 +226,25 @@ namespace Fig
|
||||
return parseVarDecl(true);
|
||||
}
|
||||
}
|
||||
else if (currentToken().type == TokenType::Variable)
|
||||
if (currentToken().type == TokenType::Variable)
|
||||
{
|
||||
return parseVarDecl(false);
|
||||
}
|
||||
else
|
||||
if (currentToken().type == TokenType::If)
|
||||
{
|
||||
const auto &expr_result = parseExpression(0);
|
||||
if (!expr_result)
|
||||
{
|
||||
return std::unexpected(expr_result.error());
|
||||
}
|
||||
ExprStmt *exprStmt = new ExprStmt(*expr_result);
|
||||
if (!match(TokenType::Semicolon))
|
||||
{
|
||||
return std::unexpected(makeExpectSemicolonError());
|
||||
}
|
||||
return exprStmt;
|
||||
return parseIfStmt();
|
||||
}
|
||||
|
||||
const auto &expr_result = parseExpression(0);
|
||||
if (!expr_result)
|
||||
{
|
||||
return std::unexpected(expr_result.error());
|
||||
}
|
||||
ExprStmt *exprStmt = new ExprStmt(*expr_result);
|
||||
if (!match(TokenType::Semicolon))
|
||||
{
|
||||
return std::unexpected(makeExpectSemicolonError());
|
||||
}
|
||||
return exprStmt;
|
||||
}
|
||||
}; // namespace Fig
|
||||
Reference in New Issue
Block a user