Add @icase decorator
This commit is contained in:
+35
-1
@@ -38,6 +38,7 @@ enum Term {
|
|||||||
mod kw {
|
mod kw {
|
||||||
syn::custom_keyword!(ANY);
|
syn::custom_keyword!(ANY);
|
||||||
syn::custom_keyword!(EOI);
|
syn::custom_keyword!(EOI);
|
||||||
|
syn::custom_keyword!(icase);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Grammar {
|
impl Parse for Grammar {
|
||||||
@@ -50,9 +51,23 @@ impl Parse for Grammar {
|
|||||||
|
|
||||||
impl Parse for Rule {
|
impl Parse for Rule {
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
let mut icase = false;
|
||||||
|
if input.parse::<Token![@]>().is_ok() {
|
||||||
|
let look = input.lookahead1();
|
||||||
|
if look.peek(kw::icase) {
|
||||||
|
input.parse::<kw::icase>()?;
|
||||||
|
icase = true;
|
||||||
|
} else {
|
||||||
|
return Err(look.error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let name = input.parse()?;
|
let name = input.parse()?;
|
||||||
input.parse::<Token![=]>()?;
|
input.parse::<Token![=]>()?;
|
||||||
let definition = input.parse()?;
|
let mut definition: Term = input.parse()?;
|
||||||
|
if icase {
|
||||||
|
definition.set_icase();
|
||||||
|
}
|
||||||
Ok(Self { name, definition })
|
Ok(Self { name, definition })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,6 +279,25 @@ impl Term {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_icase(&mut self) {
|
||||||
|
match self {
|
||||||
|
Term::Literal(_, icase) | Term::Range(_, icase) => {
|
||||||
|
*icase = true;
|
||||||
|
}
|
||||||
|
Term::Choice(terms) | Term::Sequence(terms) => {
|
||||||
|
terms.iter_mut().for_each(|x| x.set_icase());
|
||||||
|
}
|
||||||
|
Term::NegLookahead(term)
|
||||||
|
| Term::Optional(term)
|
||||||
|
| Term::Plus(term)
|
||||||
|
| Term::PosLookahead(term)
|
||||||
|
| Term::Star(term) => {
|
||||||
|
term.set_icase();
|
||||||
|
}
|
||||||
|
Term::AnyChar | Term::EOI | Term::Rule(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
|
|||||||
@@ -106,6 +106,10 @@ mod tests {
|
|||||||
quoted = dq ("\\" ANY / !dq ANY)* dq;
|
quoted = dq ("\\" ANY / !dq ANY)* dq;
|
||||||
|
|
||||||
case_sensitivity = "Strict " ('a'..'z')+ ", loose "i ('a'..'z'i)+;
|
case_sensitivity = "Strict " ('a'..'z')+ ", loose "i ('a'..'z'i)+;
|
||||||
|
|
||||||
|
@icase
|
||||||
|
hex_config = "let " var_name " = 0x" ('a'..'f' / '0'..'9')+;
|
||||||
|
var_name = "foo" / "bar"; // case must match
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse<T: Fn(&mut ParseState) -> bool>(rule: T, s: &str) -> bool {
|
fn parse<T: Fn(&mut ParseState) -> bool>(rule: T, s: &str) -> bool {
|
||||||
@@ -194,4 +198,12 @@ mod tests {
|
|||||||
assert!(parse(case_sensitivity, "Strict abc, loose XYZ"));
|
assert!(parse(case_sensitivity, "Strict abc, loose XYZ"));
|
||||||
assert!(parse(case_sensitivity, "Strict abc, LoOsE XyZ"));
|
assert!(parse(case_sensitivity, "Strict abc, LoOsE XyZ"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_icase_decorator() {
|
||||||
|
assert!(parse(hex_config, "let foo = 0xc0ffee"));
|
||||||
|
assert!(parse(hex_config, "LET bar = 0XCAFE"));
|
||||||
|
assert!(!parse(hex_config, "let Foo = 0xc0ffee"));
|
||||||
|
assert!(!parse(hex_config, "let BAR = 0xcafe"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user