diff options
author | Greg Brown <gmb60@cam.ac.uk> | 2021-01-09 14:31:02 +0000 |
---|---|---|
committer | Greg Brown <gmb60@cam.ac.uk> | 2021-01-09 14:31:02 +0000 |
commit | 0d01692c97ea8ca6fc4b229e5b9678cb252bceda (patch) | |
tree | 6c5ed07740b814f50dddbc6afaefc21c11dc3440 /src | |
parent | 487ce4fe0fa081f58d790d7d6417bf7d2659197c (diff) |
Introduce chomp as a procedural macro.
Add a bunch of tests.
Fix chomp and chewed so autochomp compiles.
Diffstat (limited to 'src')
-rw-r--r-- | src/chomp/check/inline.rs | 119 | ||||
-rw-r--r-- | src/chomp/error.rs | 17 | ||||
-rw-r--r-- | src/lower/rust.rs | 5 |
3 files changed, 136 insertions, 5 deletions
diff --git a/src/chomp/check/inline.rs b/src/chomp/check/inline.rs index 43a2eb8..da501f1 100644 --- a/src/chomp/check/inline.rs +++ b/src/chomp/check/inline.rs @@ -158,7 +158,7 @@ mod tests { None, ) .into(), - None + None, ); let inlined = expr.fold(&mut InlineCalls::new(function)); assert_eq!( @@ -208,7 +208,7 @@ mod tests { None, ) .into(), - None + None, ); let inlined = expr.fold(&mut InlineCalls::new(function)); assert_eq!( @@ -231,4 +231,119 @@ mod tests { .into()) ) } + + #[test] + fn test_inline_double_subst() { + let expr = Call::new( + Name::Spanless("opt".to_string()), + vec![Call::new( + Name::Spanless("opt".to_string()), + vec![Literal::Spanless("x".to_string()).into()], + None, + ) + .into()], + None, + ); + let inlined = expr.fold(&mut InlineCalls::new(opt())); + assert_eq!( + inlined, + Ok(Alt::new( + Epsilon::default().into(), + None, + Alt::new( + Epsilon::default().into(), + None, + Literal::Spanless("x".to_string()).into() + ) + .into() + ) + .into()) + ) + } + + #[test] + fn test_inline_call_args() { + let expr = Fix::new( + Name::Spanless("rec".to_string()), + Cat::new( + Literal::Spanless("a".to_string()).into(), + None, + Call::new( + Name::Spanless("opt".to_string()), + vec![Cat::new( + Cat::new( + Literal::Spanless("a".to_string()).into(), + None, + Fix::new( + Name::Spanless("star".to_string()), + Call::new( + Name::Spanless("opt".to_string()), + vec![Cat::new( + Literal::Spanless(" ".to_string()).into(), + None, + Variable::new(Name::Spanless("star".to_string()), 0).into(), + ) + .into()], + None, + ) + .into(), + None, + ) + .into(), + ) + .into(), + None, + Variable::new(Name::Spanless("rec".to_string()), 0).into(), + ) + .into()], + None, + ) + .into(), + ) + .into(), + None, + ); + let inlined = expr.fold(&mut InlineCalls::new(opt())); + assert_eq!(inlined, + Ok(Fix::new( + Name::Spanless("rec".to_string()), + Cat::new( + Literal::Spanless("a".to_string()).into(), + None, + Alt::new( + Epsilon::default().into(), + None, + Cat::new( + Cat::new( + Literal::Spanless("a".to_string()).into(), + None, + Fix::new( + Name::Spanless("star".to_string()), + Alt::new( + Epsilon::default().into(), + None, + Cat::new( + Literal::Spanless(" ".to_string()).into(), + None, + Variable::new(Name::Spanless("star".to_string()), 0).into(), + ) + .into() + ) + .into(), + None, + ) + .into(), + ) + .into(), + None, + Variable::new(Name::Spanless("rec".to_string()), 0).into(), + ) + .into(), + ) + .into(), + ) + .into(), + None, + ).into())) + } } diff --git a/src/chomp/error.rs b/src/chomp/error.rs index ffcbdd0..e7e4660 100644 --- a/src/chomp/error.rs +++ b/src/chomp/error.rs @@ -358,6 +358,19 @@ pub enum SubstituteError { WrongArgCount { call: Call, expected: usize }, } +impl From<SubstituteError> for syn::Error { + fn from(e: SubstituteError) -> Self { + match e { + SubstituteError::FreeParameter(param) => { + Self::new(param.name().span().unwrap_or_else(Span::call_site), format!("undeclared variable `{}'", param.name())) + } + SubstituteError::WrongArgCount { call, expected } => { + Self::new(call.span().unwrap_or_else(Span::call_site), format!("wrong number of arguments. Expected {}, got {}", expected, call.args().len())) + } + } + } +} + impl Display for SubstituteError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -378,8 +391,8 @@ impl Display for SubstituteError { "{}:{}: wrong number of arguments. Expected {}, got {}", start.line, start.column, - call.args().len(), - expected + expected, + call.args().len() ) } } diff --git a/src/lower/rust.rs b/src/lower/rust.rs index 74deb73..7931306 100644 --- a/src/lower/rust.rs +++ b/src/lower/rust.rs @@ -75,7 +75,7 @@ impl Backend for RustBackend { impl Parse for #name { fn take<P: Parser + ?Sized>(input: &mut P) -> Result<Self, TakeError> { - input.take_str(#lit).map(|()| #name) + input.consume_str(#lit).map(|()| #name) } } }; @@ -206,8 +206,11 @@ impl Backend for RustBackend { TokenStream::new(), BTreeSet::new(), )); + self.context.push(id); let inner = inner.gen(self); + self.context.pop(); + let inner_ty = self.data[inner].0.clone(); let tokens = quote! { #[derive(Clone, Debug, Eq, Hash, PartialEq)] |