mun_syntax 0.4.0

Parsing functionality for the Mun programming language
Documentation
use super::*;

pub(super) const PATH_FIRST: TokenSet =
    TokenSet::new(&[IDENT, T![super], T![self], T![package], T![::]]);

pub(super) fn is_path_start(p: &Parser) -> bool {
    matches!(p.current(), IDENT | T![self] | T![super] | T![package])
}

pub(super) fn is_use_path_start(p: &Parser, top_level: bool) -> bool {
    if top_level {
        matches!(p.current(), IDENT | T![self] | T![super] | T![package])
    } else {
        matches!(p.current(), IDENT | T![self])
    }
}

pub(super) fn type_path(p: &mut Parser) {
    path(p, Mode::Type, true)
}
pub(super) fn expr_path(p: &mut Parser) {
    path(p, Mode::Expr, true)
}
pub(super) fn use_path(p: &mut Parser, top_level: bool) {
    path(p, Mode::Use, top_level)
}

#[derive(Clone, Copy, Eq, PartialEq)]
enum Mode {
    Type,
    Expr,
    Use,
}

fn path(p: &mut Parser, mode: Mode, top_level: bool) {
    let path = p.start();
    path_segment(p, mode, top_level);
    let mut qualifier = path.complete(p, PATH);
    loop {
        let use_tree = matches!(p.nth(2), T![*] | T!['{']);
        if p.at(T![::]) && !use_tree {
            let path = qualifier.precede(p);
            p.bump(T![::]);
            path_segment(p, mode, false);
            let path = path.complete(p, PATH);
            qualifier = path;
        } else {
            break;
        }
    }
}

fn path_segment(p: &mut Parser, _mode: Mode, top_level: bool) {
    let m = p.start();
    match p.current() {
        IDENT => {
            name_ref(p);
        }
        T![super] | T![package] if top_level => p.bump_any(),
        T![self] => p.bump(T![self]),
        _ => p.error_recover(
            "expected identifier",
            declarations::DECLARATION_RECOVERY_SET,
        ),
    }
    m.complete(p, PATH_SEGMENT);
}