use crate::SyntaxKind::{
AUTHOR_WARNING, EMPTY_LINE, HASH, KW_TODO, L_BRACE, MINUS, NEWLINE, PLUS, R_BRACE, SOURCE_FILE,
STAR, STRAY_CLOSING_BRACE, TILDE, WHITESPACE,
};
use super::Parser;
pub(crate) fn source_file(p: &mut Parser<'_, '_>) {
p.start_node(SOURCE_FILE);
while !p.at_eof() {
p.skip_ws();
if p.at_eof() {
break;
}
let before = p.pos();
top_level_statement(p);
if p.pos() == before {
p.error_recover("unexpected token");
}
}
p.finish_node();
}
fn top_level_statement(p: &mut Parser<'_, '_>) {
if super::knot::at_knot(p) {
super::knot::knot_definition(p);
return;
}
if super::knot::at_stitch(p) {
super::knot::stitch_definition(p);
return;
}
if super::declaration::at_declaration(p) {
super::declaration::declaration(p);
return;
}
line(p);
}
pub(crate) fn line(p: &mut Parser<'_, '_>) {
match p.current() {
NEWLINE => {
p.start_node(EMPTY_LINE);
p.bump();
p.finish_node();
}
HASH => {
super::tag::tag_line(p);
}
KW_TODO => {
author_warning(p);
}
R_BRACE => {
stray_closing_brace(p);
}
TILDE => {
super::logic::logic_line(p);
}
STAR | PLUS => {
super::choice::choice(p);
}
MINUS => {
super::gather::gather_line(p);
}
L_BRACE if is_multiline_block(p) => {
super::inline::multiline_block(p);
if p.at(NEWLINE) {
p.bump();
}
}
_ => {
super::content::content_line(p);
}
}
}
fn is_multiline_block(p: &Parser<'_, '_>) -> bool {
let mut i = 1; loop {
match p.nth_raw(i) {
WHITESPACE => i += 1,
NEWLINE => return true,
_ => return false,
}
}
}
fn author_warning(p: &mut Parser<'_, '_>) {
p.start_node(AUTHOR_WARNING);
p.bump(); while !p.at_eof() && p.nth_raw(0) != NEWLINE {
p.bump();
}
if p.at(NEWLINE) {
p.bump();
}
p.finish_node();
}
fn stray_closing_brace(p: &mut Parser<'_, '_>) {
p.start_node(STRAY_CLOSING_BRACE);
p.skip_ws();
p.bump(); p.skip_ws();
if p.at(NEWLINE) {
p.bump();
}
p.finish_node();
}