use std::str::FromStr;
use crate::parser::{ParseError, lexer, ast, Error};
use lexer::Tok;
use ast::Ast;
grammar();
pub Ast: ast::Ast = {
#[precedence(level="0")]
Term,
#[precedence(level="1")] #[assoc(side="right")]
<t: Ast> "?" => Ast::optional(t),
<t: Ast> "{" <n: Nat> "}" =>? {
if let Some(n) = n {
Ok(Ast::quantifier_exact(t, n))
} else {
Err(ParseError::User { error: Error::ParseError })
}
},
<t: Ast> "{" <min: Nat> "," <max: Nat> "}" =>? {
if let (Some(min), Some(max)) = (min, max) {
Ok(Ast::quantifier_range(t, min, max))
} else {
Err(ParseError::User { error: Error::ParseError })
}
},
#[precedence(level="2")] #[assoc(side="left")]
<lhs: Ast> <rhs: Ast> => Ast::then(lhs, rhs),
#[precedence(level="3")] #[assoc(side="left")]
<lhs: Ast> "|" <rhs: Ast> => Ast::or(lhs, rhs),
}
Term: ast::Ast = {
<c: "char"> => Ast::char(c),
<"digit"> => Ast::digit(),
<" "> => Ast::space(),
"(" <p: Ast> ")" => p,
"(" "!" <p: Ast> ")" => Ast::case_sensitive(p)
}
Nat: Option<u32> = <s: NatSeq> => s.as_deref().map(u32::from_str)?.ok();
NatSeq: Option<String> = {
<c: "char"> => {
if c.is_ascii_digit() {
Some(String::from(c))
} else {
None
}
},
<substr: NatSeq> <c: "char"> => {
if let Some(mut substr) = substr {
if c.is_ascii_digit() {
substr.push(c);
Some(substr)
} else {
None
}
} else {
None
}
}
}
extern {
type Location = usize;
type Error = Error;
enum Tok {
"|" => lexer::Tok::Or,
"?" => lexer::Tok::QMark,
"(" => lexer::Tok::LParen,
")" => lexer::Tok::RParen,
"{" => lexer::Tok::LCurly,
"}" => lexer::Tok::RCurly,
"!" => lexer::Tok::Exclam,
"," => lexer::Tok::Comma,
"char" => lexer::Tok::Char { c: <char>, .. },
"digit" => lexer::Tok::Digit,
" " => lexer::Tok::Space
}
}