use crate::SyntaxKind::{
COLON, COMMA, CONST_DECL, EQ, EXTERN_DECL, FLAGS_DECL, FLAGS_MEMBER, FLAGS_MEMBER_LIST,
FLOW_DECL, FN_DECL, IDENT, IMPORT_DECL, KW_AS, KW_EXTERN, KW_FLAGS, KW_FLOW, KW_FN, KW_MODULE,
KW_REF, KW_STRUCT, L_BRACE, L_PAREN, MODULE_DECL, PARAM, PARAM_LIST, R_BRACE, R_PAREN,
STRUCT_DECL, STRUCT_FIELD, USE_DECL, USE_TREE, USE_TREE_LIST, VAR_DECL,
};
use super::Parser;
pub(crate) fn at_flow_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_FLOW) && p.nth(1) == IDENT && matches!(p.nth(2), L_PAREN | L_BRACE)
}
pub(crate) fn at_fn_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_FN) && p.nth(1) == IDENT && matches!(p.nth(2), L_PAREN | L_BRACE)
}
pub(crate) fn at_binding_decl(p: &Parser<'_, '_>) -> bool {
p.nth(1) == IDENT && p.nth(2) == EQ
}
pub(crate) fn at_flags_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_FLAGS) && p.nth(1) == IDENT && p.nth(2) == EQ
}
pub(crate) fn at_struct_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_STRUCT) && p.nth(1) == IDENT && p.nth(2) == L_BRACE
}
pub(crate) fn at_extern_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_EXTERN) && p.nth(1) == IDENT && p.nth(2) == L_PAREN
}
pub(crate) fn at_import_decl(p: &Parser<'_, '_>) -> bool {
p.nth(1) == IDENT
}
pub(crate) fn at_use_decl(p: &Parser<'_, '_>) -> bool {
matches!(p.nth(1), IDENT | crate::SyntaxKind::COLON_COLON)
}
pub(crate) fn at_module_decl(p: &Parser<'_, '_>) -> bool {
p.at(KW_MODULE) && p.nth(1) == IDENT && p.nth(2) == L_BRACE
}
pub(crate) fn flow_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, FLOW_DECL, doc);
p.bump(); p.expect(IDENT);
if p.at(L_PAREN) {
param_list(p);
}
if p.at(L_BRACE) {
super::block::block(p);
} else {
p.error("expected a braced body after the flow header".into());
}
p.finish_node();
}
pub(crate) fn fn_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, FN_DECL, doc);
p.bump(); p.expect(IDENT);
if p.at(L_PAREN) {
param_list(p);
}
if p.at(L_BRACE) {
super::block::block(p);
} else {
p.error("expected a braced body after the fn header".into());
}
p.finish_node();
}
fn param_list(p: &mut Parser<'_, '_>) {
p.start_node(PARAM_LIST);
p.expect(L_PAREN);
p.skip_ws_and_newlines();
while p.peek_skip_nl() != R_PAREN && !p.at_eof() {
let before = p.pos();
param(p);
if p.pos() == before {
p.error_recover("unexpected token in parameter list");
continue;
}
p.skip_ws_and_newlines();
if !p.eat(COMMA) {
break;
}
p.skip_ws_and_newlines();
}
p.expect(R_PAREN);
p.finish_node();
}
fn param(p: &mut Parser<'_, '_>) {
p.start_node(PARAM);
p.eat(KW_REF);
p.expect(IDENT);
p.finish_node();
}
pub(crate) fn var_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, VAR_DECL, doc);
p.bump(); p.expect(IDENT);
if p.eat(crate::SyntaxKind::EQ) {
super::expr::expression(p);
}
p.finish_node();
}
pub(crate) fn const_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, CONST_DECL, doc);
p.bump(); p.expect(IDENT);
if p.eat(crate::SyntaxKind::EQ) {
super::expr::expression(p);
}
p.finish_node();
}
pub(crate) fn flags_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, FLAGS_DECL, doc);
p.bump(); p.expect(IDENT);
p.expect(crate::SyntaxKind::EQ);
flags_member_list(p);
p.finish_node();
}
fn flags_member_list(p: &mut Parser<'_, '_>) {
p.start_node(FLAGS_MEMBER_LIST);
loop {
let before = p.pos();
flags_member(p);
if p.pos() == before {
break;
}
if !p.eat(COMMA) {
break;
}
}
p.finish_node();
}
fn flags_member(p: &mut Parser<'_, '_>) {
if !p.at(IDENT) && !p.at(L_PAREN) {
return;
}
p.start_node(FLAGS_MEMBER);
if p.eat(L_PAREN) {
p.expect(IDENT);
p.expect(R_PAREN);
} else {
p.expect(IDENT);
}
p.finish_node();
}
pub(crate) fn struct_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, STRUCT_DECL, doc);
p.bump(); p.expect(IDENT);
p.expect(L_BRACE);
p.skip_ws_and_newlines();
while p.peek_skip_nl() != R_BRACE && !p.at_eof() {
let before = p.pos();
struct_field(p);
if p.pos() == before {
p.error_recover("unexpected token in struct body");
p.skip_ws_and_newlines();
continue;
}
p.skip_ws_and_newlines();
p.eat(COMMA);
p.skip_ws_and_newlines();
}
p.expect(R_BRACE);
p.finish_node();
}
fn struct_field(p: &mut Parser<'_, '_>) {
if !p.at(IDENT) {
return;
}
p.start_node(STRUCT_FIELD);
p.expect(IDENT);
p.expect(COLON);
super::expr::path(p);
p.finish_node();
}
pub(crate) fn extern_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, EXTERN_DECL, doc);
p.bump(); p.expect(IDENT);
if p.at(L_PAREN) {
param_list(p);
}
p.finish_node();
}
pub(crate) fn import_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, IMPORT_DECL, doc);
p.bump(); super::expr::path(p);
p.finish_node();
}
pub(crate) fn use_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, USE_DECL, doc);
p.bump(); use_tree(p);
p.eat(crate::SyntaxKind::SEMICOLON);
p.finish_node();
}
fn use_tree(p: &mut Parser<'_, '_>) {
p.start_node(USE_TREE);
if p.at(IDENT) {
p.expect(IDENT);
loop {
if p.at(crate::SyntaxKind::COLON_COLON) {
if p.nth(1) == L_BRACE {
p.expect(crate::SyntaxKind::COLON_COLON);
use_tree_list(p);
break;
}
p.expect(crate::SyntaxKind::COLON_COLON);
p.expect(IDENT);
} else {
break;
}
}
if p.eat(KW_AS) {
p.expect(IDENT);
}
} else if p.at(L_BRACE) {
use_tree_list(p);
} else {
p.error("expected a path or `{` in a use tree".into());
}
p.finish_node();
}
fn use_tree_list(p: &mut Parser<'_, '_>) {
p.start_node(USE_TREE_LIST);
p.expect(L_BRACE);
p.skip_ws_and_newlines();
while p.peek_skip_nl() != R_BRACE && !p.at_eof() {
let before = p.pos();
use_tree(p);
if p.pos() == before {
p.error_recover("unexpected token in use-tree list");
p.skip_ws_and_newlines();
continue;
}
p.skip_ws_and_newlines();
if !p.eat(COMMA) {
break;
}
p.skip_ws_and_newlines();
}
p.expect(R_BRACE);
p.finish_node();
}
pub(crate) fn module_decl(p: &mut Parser<'_, '_>, doc: Option<rowan::Checkpoint>) {
super::doc_comment::open_with_doc(p, MODULE_DECL, doc);
p.bump(); p.expect(IDENT);
if p.at(L_BRACE) {
super::block::block(p);
} else {
p.error("expected a braced body after the module header".into());
}
p.finish_node();
}