Crate gramma

source ·
Expand description
use gramma::{
    ast::InfixChain,
    define_rule,
    define_token,
    display_tree,
    parse_tree,
};

define_token!(
    #[pattern(exact = "(")]
    pub struct LeftParen;
    #[pattern(exact = ")")]
    pub struct RightParen;
    #[pattern(exact = "[")]
    pub struct LeftBracket;
    #[pattern(exact = "]")]
    pub struct RightBracket;
    #[pattern(exact = "+")]
    pub struct Plus;
    #[pattern(exact = "-")]
    pub struct Minus;
    #[pattern(exact = ",")]
    pub struct Comma;
    #[pattern(regex = r"[a-zA-Z_]\w*")]
    pub struct Ident;
    #[pattern(regex = r"\d+")]
    pub struct Number;
    #[pattern(regex = r"\s*")]
    pub struct Whitespace;
);

define_rule!(
    #[transform(ignore_around<Whitespace>)]
    pub enum BaseExpr {
        Parens {
            l_paren: LeftParen,
            expr: Box<Expr>,
            r_paren: RightParen,
        },
        List {
            l_bracket: LeftBracket,
            #[transform(delimited<Comma>)]
            exprs: Vec<Expr>,
            #[transform(ignore_before<Whitespace>)]
            r_bracket: RightBracket,
        },
        Ident { ident: Ident },
        Number { number: Number },
    }

    #[transform(ignore_around<Whitespace>)]
    pub enum Op {
        Plus { plus: Plus },
        Minus { minus: Minus },
    }

    pub struct Expr {
        binary_ops: InfixChain<BaseExpr, Op>,
    }
);

let src = "
    a - (b + c) + [1, 2]
";

let expr = parse_tree::<Expr, 1>(src).unwrap();

let actual_display = format!("{:#}", display_tree(src, &expr));
let expected_display = r#"
Expr -> (
    <Ident "a">,
    { "-", {
        "(",
        Expr -> (
            <Ident "b">,
            { "+", <Ident "c"> },
        ),
        ")",
    } },
    { "+", {
        "[",
        [
            Expr -> <Number "1">,
            Expr -> <Number "2">,
        ],
        "]",
    } },
)
"#.trim();

assert_eq!(actual_display, expected_display);

Re-exports§

Modules§

Macros§