peg-macros 0.6.3

Procedural macros for rust-peg. To use rust-peg, see the `peg` crate.
Documentation
pub grammar peg() for FlatTokenStream {

use crate::ast::*;
use crate::ast::Expr::*;
use crate::tokens::FlatTokenStream;
use proc_macro2::{ TokenStream, Ident, Literal, Delimiter };

pub rule peg_grammar() -> Grammar
    = doc:rust_doc_comment() visibility:rust_visibility() "grammar" name:IDENT() args:grammar_args() "for" input_type:$(rust_type()) "{" items:item()* "}"
        { Grammar { doc, visibility, name, args, input_type, items } }

rule grammar_args() -> Vec<(Ident, TokenStream)>
    = "(" args:((i:IDENT() ":" t:$(rust_type()) { (i, t) })**",") ","? ")" { args }

rule peg_rule() -> Rule
    = doc:rust_doc_comment() cached:cacheflag() visibility:rust_visibility()
      "rule" name:IDENT() ty_params:rust_ty_params()? "(" params:rule_param()**"," ")" ret_type:("->" t:$(rust_type()) {t})? "=" expr:expression() ";"?
        { Rule { doc, name, ty_params, params, expr, ret_type, visibility, cached } }

    rule cacheflag() -> bool = "#" "[" "cache" "]" {true} / {false}

    rule rust_ty_params() -> Vec<TokenStream>
        = "<" p:(($(IDENT() / LIFETIME())) ++ ",") ">" { p }

    rule rule_param() -> RuleParam
        = name:IDENT() ":" ty:(
            "rule" "<" r:$(rust_type()) ">" { RuleParamTy::Rule(r) }
            / t:$(rust_type()) { RuleParamTy::Rust(t) }
        ) { RuleParam { name, ty} }

rule item() -> Item
    = u:rust_use()     { Item::Use(u) }
    / r:peg_rule()     { Item::Rule(r) }

rule rust_doc_comment() -> Option<TokenStream> = $(("#" "[" "doc" "=" LITERAL() "]")*)?

rule rust_visibility() -> Option<TokenStream> = $("pub" PAREN_GROUP()? / "crate")?

rule rust_use() -> TokenStream
    = v:$("use" rust_path() (
        "::" "*"
        / "::" "{" ((IDENT() ("as" IDENT())?) ++ ",") "}"
        / ("as" IDENT())?
    ) ";") { v.to_owned() }

rule rust_path()
    = ("crate" "::")? IDENT() ++ "::"

rule rust_type()
    = BRACKET_GROUP()
    / "&" "mut"? LIFETIME()? rust_type()
    / "dyn" rust_type()
    / "impl" rust_type()
    / IDENT() "<" (LIFETIME() / rust_type()) ++ "," ">"
    / IDENT() "::" rust_type()
    / "(" rust_type() ** "," ")"
    / IDENT()

rule expression() -> Expr = choice()

rule choice() -> Expr = s:sequence() ++ "/" {
    if s.len() == 1 {
        s.into_iter().next().unwrap()
    } else {
        ChoiceExpr(s)
    }
}

rule sequence() -> Expr
     = elements:labeled()* code:code_block()? {
         if let Some(code) = code {
            ActionExpr(elements, Some(code.1), code.0)
         } else if elements.len() != 1 {
             ActionExpr(elements, None, false)
         } else {
             elements.into_iter().next().unwrap().expr
         }
    }

    rule code_block() -> (bool, TokenStream)
        = "{" is_cond:"?"? code:##group_body() "}" { (is_cond.is_some(), code) }

rule labeled() -> TaggedExpr
    = label:(l:IDENT() ":" {l})? expression:suffixed()
        { TaggedExpr{ name: label, expr: expression } }

rule suffixed() -> Expr
    = e:prefixed() "?" { OptionalExpr(Box::new(e)) }
    / e:prefixed() "**" count:repeatcount() sep:primary() { Repeat(Box::new(e), count, Some(Box::new(sep))) }
    / e:prefixed() "++" sep:primary() { Repeat(Box::new(e), BoundedRepeat::Plus, Some(Box::new(sep))) }
    / e:prefixed() "*" count:repeatcount() { Repeat(Box::new(e), count, None) }
    / e:prefixed() "+" { Repeat(Box::new(e), BoundedRepeat::Plus, None) }
    / prefixed()

rule repeatcount() -> BoundedRepeat
    = "<" n:repeatnum() ">" { BoundedRepeat::Exact(n) }
    / "<" min:repeatnum()? "," max:repeatnum()? ">" { BoundedRepeat::Both(min, max) }
    / { BoundedRepeat::None }

rule repeatnum() -> TokenStream = $(INTEGER() / BRACE_GROUP())

rule prefixed() -> Expr
    = "$" expression:primary() { MatchStrExpr(Box::new(expression)) }
    / "&" expression:primary() { PosAssertExpr(Box::new(expression)) }
    / "!" expression:primary() { NegAssertExpr(Box::new(expression)) }
    / primary()

#[cache]
rule primary() -> Expr
  = "precedence" "!" "{" levels:precedence_level()**"--" "}" { PrecedenceExpr{ levels:levels }}
  / "position" "!" "(" ")" { PositionExpr }
  / "quiet" "!" "{" e:expression() "}" { QuietExpr(Box::new(e)) }
  / "expected" "!" "(" s:LITERAL() ")" { FailExpr(s) }
  / &("_" / "__" / "___") name:IDENT() { RuleExpr(name, Vec::new()) }
  / name:IDENT() "(" args:(rule_arg() ** ",") ")" { RuleExpr(name, args) }
  / l:LITERAL() { LiteralExpr(l) }
  / p:BRACKET_GROUP() { PatternExpr(p) }
  / "(" "@" ")" { MarkerExpr(true) }
  / "@" { MarkerExpr(false) }
  / "##" method:IDENT() args:PAREN_GROUP() { MethodExpr(method, args) }
  / "(" expression:expression() ")" { expression }

    rule rule_arg() -> RuleArg
        = "<" e:expression() ">" { RuleArg::Peg(e) }
        / tt:$(LITERAL() / PAREN_GROUP() / IDENT()) { RuleArg::Rust(tt) }

rule precedence_level() -> PrecedenceLevel
  = operators:precedence_op()+
  { PrecedenceLevel{ operators: operators } }

rule precedence_op() -> PrecedenceOperator
  = elements:labeled()* action:BRACE_GROUP()
  { PrecedenceOperator{ elements, action } }

rule KEYWORD() = "pub" / "crate" / "rule" / "use" / "type"
rule IDENT() -> Ident = !KEYWORD() i:##ident() {i}
rule LITERAL() -> Literal = ##literal()
rule PAREN_GROUP()   -> TokenStream = ##group(Delimiter::Parenthesis)
rule BRACE_GROUP()   -> TokenStream = ##group(Delimiter::Brace)
rule BRACKET_GROUP() -> TokenStream = ##group(Delimiter::Bracket)
rule LIFETIME() = "'" IDENT()
rule INTEGER() = LITERAL()

}