lbnf 0.1.0

A crate for parsing LBNF grammar
Documentation
use std::str::FromStr;
use crate::grammar::*;

grammar;

match {
    r"\s*" => { }, // Skip whitespace
    r"--[^\n\r]*[\n\r]" => { }, // Skip `-- comments`
    r"[{]-[^-]*-+(?:[^}-][^-]*-+)*[}]" => { },  // Skip `{- comments -}`
    r"-?[0-9]+" => TokInt,
    r"-?([0-9]+[.]([0-9]*)?|[.][0-9]+)" => TokDouble,
    r#""(:?(:?\\")|[^"\n\r])*""# => TokString,
    r"'[[:ascii:]]'" => TokChar,
    r"[a-zA-Z_][a-zA-Z0-9_]*" => TokIdent,
    "_"   => Wild,
    "."   => Dot,
    "::=" => Assign,
    ";"   => Semi,
    ":"   => Colon,
    "["   => BrackO,
    "]"   => BrackC,
    "("   => ParenO,
    ")"   => ParenC,
    ","   => Comma,
}

pub Grammar: Grammar = {
    <definitions:(<Def>)*> => Grammar {<>}
};

Def: Def = {
  <Label> Dot <Cat> Assign <(<Item>)*> Semi => Def::Rule(<>),
  <Ident> <(<Exp>)*> Semi => Def::Macro(<>),
};

Cat: Cat = {
  BrackO <Cat> BrackC => Cat::ListCat(Box::new(<>)),
  <Ident>       => Cat::IdCat(<>),  
};

Item: Item = {
  <String> => Item::Terminal(<>),
  <Cat>    => Item::NTerminal(<>),
};

Exp: Exp = {
  <Ident>       => Exp::Var(<>),
  <Int>         => Exp::LitInt(<>),
  <Double>      => Exp::LitDouble(<>),
  <Char>        => Exp::LitChar(<>),
  <String>      => Exp::LitString(<>),
  ParenO <Exp> ParenC => <>,
};

Label: Label = {
  Wild                              => Label::Wild,
  BrackO BrackC                     => Label::ListE,
  ParenO Colon ParenC               => Label::ListCons,
  ParenO Colon BrackO BrackC ParenC => Label::ListOne,
  <Ident>                           => Label::Id(<>),
};
 
CommaSep<T>: Vec<T> = {
    <mut v:(<T> Comma)*> <e:T?> => match e {
        None => v,
        Some(e) => {
            v.push(e);
            v
        }
    }
};

Int: i64 = <TokInt> => i64::from_str(<>).unwrap();
Double: f64    = <TokDouble> => f64::from_str(<>).unwrap();
String: String = <s:TokString> => s[1..s.len() - 1].replace("\\\"", "\"");
Char: char     = <s:TokChar> => s.chars().skip(1).next().unwrap() ;
Ident: Ident   = <s:TokIdent> => Ident(s.to_string());