use crate::SyntaxKind;
use crate::parser::{Parser, TokenSet, syntax_codes as sc};
pub(crate) mod clause;
pub(crate) mod expression;
pub(crate) mod pattern;
pub(crate) mod statement;
pub(crate) const CLAUSE_START: TokenSet = TokenSet::new(&[
SyntaxKind::MATCH_KW,
SyntaxKind::OPTIONAL_KW,
SyntaxKind::WHERE_KW,
SyntaxKind::WITH_KW,
SyntaxKind::RETURN_KW,
SyntaxKind::CREATE_KW,
SyntaxKind::MERGE_KW,
SyntaxKind::SET_KW,
SyntaxKind::REMOVE_KW,
SyntaxKind::DELETE_KW,
SyntaxKind::DETACH_KW,
SyntaxKind::UNWIND_KW,
SyntaxKind::CALL_KW,
]);
pub(crate) fn source_file(p: &mut Parser<'_>) {
let m = p.start();
if p.current() != SyntaxKind::EOF
&& !p.at_ts(CLAUSE_START)
&& !p.at(SyntaxKind::SEMI)
&& !p.at(SyntaxKind::UNION_KW)
{
p.error_code(sc::EXPECTED_STATEMENT, "expected statement");
p.recover_until(TokenSet::EMPTY);
}
while p.current() != SyntaxKind::EOF {
let pos_before = p.position();
if p.at(SyntaxKind::SEMI) {
p.bump(SyntaxKind::SEMI);
continue;
}
statement::statement(p);
if p.at(SyntaxKind::SEMI) {
p.bump(SyntaxKind::SEMI);
} else if p.current() != SyntaxKind::EOF {
if !p.at_ts(CLAUSE_START) && !p.at(SyntaxKind::UNION_KW) {
p.error_code(
sc::EXPECTED_SEMICOLON_OR_EOF,
"expected ';' or end of input",
);
p.recover_until(TokenSet::EMPTY);
}
}
if p.position() == pos_before {
let err = p.start();
p.error_code(sc::UNEXPECTED_TOKEN, "unexpected token");
p.bump_any();
err.complete(p, SyntaxKind::ERROR);
}
}
m.complete(p, SyntaxKind::SOURCE_FILE);
}