Parsing for while, break, and continue statements, following #340.

This commit is contained in:
Richard Smith
2021-04-19 17:09:54 -07:00
parent 146d995995
commit 153d92b390
4 changed files with 91 additions and 0 deletions
+45
View File
@@ -86,6 +86,17 @@ struct ExpectedSemiAfterExpression
"Expected `;` after expression.";
};
struct ExpectedSemiAfter : SimpleDiagnostic<ExpectedSemiAfter> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
static constexpr const char* Message = "Expected `;` after `{0}`.";
TokenKind preceding;
auto Format() -> std::string {
return llvm::formatv(Message, preceding.GetFixedSpelling()).str();
}
};
struct ExpectedIdentifierAfterDot
: SimpleDiagnostic<ExpectedIdentifierAfterDot> {
static constexpr llvm::StringLiteral ShortName = "syntax-error";
@@ -758,6 +769,31 @@ auto ParseTree::Parser::ParseIfStatement() -> llvm::Optional<Node> {
/*has_errors=*/!cond || !then_case || else_has_errors);
}
auto ParseTree::Parser::ParseWhileStatement() -> llvm::Optional<Node> {
auto start = StartSubtree();
auto while_token = Consume(TokenKind::WhileKeyword());
auto cond = ParseParenCondition(TokenKind::WhileKeyword());
auto body = ParseStatement();
return AddNode(ParseNodeKind::WhileStatement(), while_token, start,
/*has_errors=*/!cond || !body);
}
auto ParseTree::Parser::ParseKeywordStatement(ParseNodeKind kind)
-> llvm::Optional<Node> {
auto keyword_kind = tokens.GetKind(*position);
assert(keyword_kind.IsKeyword());
auto start = StartSubtree();
auto keyword = Consume(keyword_kind);
auto semi =
ConsumeAndAddLeafNodeIf(TokenKind::Semi(), ParseNodeKind::StatementEnd());
if (!semi) {
emitter.EmitError<ExpectedSemiAfter>(*position,
{.preceding = keyword_kind});
}
return AddNode(kind, keyword, start, /*has_errors=*/!semi);
}
auto ParseTree::Parser::ParseStatement() -> llvm::Optional<Node> {
switch (tokens.GetKind(*position)) {
case TokenKind::VarKeyword():
@@ -766,6 +802,15 @@ auto ParseTree::Parser::ParseStatement() -> llvm::Optional<Node> {
case TokenKind::IfKeyword():
return ParseIfStatement();
case TokenKind::WhileKeyword():
return ParseWhileStatement();
case TokenKind::ContinueKeyword():
return ParseKeywordStatement(ParseNodeKind::ContinueStatement());
case TokenKind::BreakKeyword():
return ParseKeywordStatement(ParseNodeKind::BreakStatement());
case TokenKind::OpenCurlyBrace():
return ParseCodeBlock();