Repository: kevinmehall/rust-peg (language: rust)

Issue:
Control flow in {? } blocks
Reopening of #133.

> I tried to use {? } blocks, but could not compiled.
{? } blocks seem to require parser::RuleResult rather than std::result::Result, and I don't know the arguments of parser::RuleResult::Matched.
> Sorry, it was my confusion that I used return statement in a loop in {? } block.

IMO, this is a bug and not a user error. I'd expect to be able to use the full power of control flow, but I can't.

Workaround: wrap the code in a closure:

```rust
{?
    let dummy_closure = || {
        // Business logic in here, including control flow like the ?-operator
    };
    dummy_closure()
}
```



Discussion / hints:

Fix patch:
diff --git a/peg-macros/ast.rs b/peg-macros/ast.rs
index e3f68c3..971176a 100644
--- a/peg-macros/ast.rs
+++ b/peg-macros/ast.rs
@@ -1,4 +1,4 @@
-use proc_macro2::{Ident, Literal, TokenStream};
+use proc_macro2::{Ident, Literal, Group, TokenStream};
 
 #[derive(Debug)]
 pub struct Grammar {
@@ -58,7 +58,7 @@ pub struct TaggedExpr {
 #[derive(Debug, Clone)]
 pub enum Expr {
     LiteralExpr(Literal),
-    PatternExpr(TokenStream),
+    PatternExpr(Group),
     RuleExpr(Ident, Vec<RuleArg>),
     MethodExpr(Ident, TokenStream),
     ChoiceExpr(Vec<Expr>),
@@ -66,11 +66,7 @@ pub enum Expr {
     Repeat(Box<Expr>, BoundedRepeat, /*sep*/ Option<Box<Expr>>),
     PosAssertExpr(Box<Expr>),
     NegAssertExpr(Box<Expr>),
-    ActionExpr(
-        Vec<TaggedExpr>,
-        /*action*/ Option<TokenStream>,
-        /*cond*/ bool,
-    ),
+    ActionExpr(Vec<TaggedExpr>, Option<Group>),
     MatchStrExpr(Box<Expr>),
     PositionExpr,
     QuietExpr(Box<Expr>),
@@ -95,7 +91,7 @@ pub struct PrecedenceLevel {
 #[derive(Debug, Clone)]
 pub struct PrecedenceOperator {
     pub elements: Vec<TaggedExpr>,
-    pub action: TokenStream,
+    pub action: Group,
 }
 
 #[derive(Debug, Clone)]
diff --git a/peg-macros/grammar.rs b/peg-macros/grammar.rs
index 910b06b..b6f54bd 100644
--- a/peg-macros/grammar.rs
+++ b/peg-macros/grammar.rs
@@ -19,7 +19,7 @@ pub mod peg {
     use crate::ast::Expr::*;
     use crate::ast::*;
     use crate::tokens::FlatTokenStream;
-    use proc_macro2::{Delimiter, Ident, Literal, TokenStream};
+    use proc_macro2::{Delimiter, Group, Ident, Literal, TokenStream};
     pub fn peg_grammar<'input>(
         __input: &'input Input,
     ) -> ::std::result::Result<Grammar, ::peg::error::ParseError<PositionRepr>> {
@@ -113,7 +113,7 @@ pub mod peg {
                                                                     input_type,
                                                                 ) => {
                                                                     let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "{") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"{\"") } ;
-                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! () ; loop { let __pos = __repeat_pos ; let __step_res = __parse_item (__input , __state , __err_state , __pos) ; match __step_res { :: peg :: RuleResult :: Matched (__newpos , __value) => { __repeat_pos = __newpos ; __repeat_value . push (__value) ; } , :: peg :: RuleResult :: Failed => { break ; } } } :: peg :: RuleResult :: Matched (__repeat_pos , __repeat_value) } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , items) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "}") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"}\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { Grammar { doc , visibility , name , args , input_type , items } }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = { let mut __repeat_pos = __pos ; let mut __repeat_value = vec ! () ; loop { let __pos = __repeat_pos ; let __step_res = __parse_item (__input , __state , __err_state , __pos) ; match __step_res { :: peg :: RuleResult :: Matched (__newpos , __value) => { __repeat_pos = __newpos ; __repeat_value . push (__value) ; } , :: peg :: RuleResult :: Failed => { break ; } } } :: peg :: RuleResult :: Matched (__repeat_pos , __repeat_value) } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , items) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "}") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"}\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { Grammar { doc , visibility , name , args , input_type , items } }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                 }
                                                                 ::peg::RuleResult::Failed => {
                                                                     ::peg::RuleResult::Failed
@@ -229,9 +229,10 @@ pub mod peg {
                                                 };
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, t) => {
-                                                        ::peg::RuleResult::Matched(__pos, {
-                                                            (i, t)
-                                                        })
+                                                        ::peg::RuleResult::Matched(
+                                                            __pos,
+                                                            (|| (i, t))(),
+                                                        )
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -287,7 +288,7 @@ pub mod peg {
                                     };
                                     match __seq_res {
                                         ::peg::RuleResult::Matched(__pos, _) => {
-                                            ::peg::RuleResult::Matched(__pos, { args })
+                                            ::peg::RuleResult::Matched(__pos, (|| args)())
                                         }
                                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                     }
@@ -395,7 +396,7 @@ pub mod peg {
                                                                             __repeat_value,
                                                                         )
                                                                     };
-                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , params) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "->") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"->\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = { let str_start = __pos ; match match __parse_rust_type (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , :: peg :: ParseSlice :: parse_slice (__input , str_start , __newpos)) } , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , t) => { :: peg :: RuleResult :: Matched (__pos , { t }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } { :: peg :: RuleResult :: Matched (__newpos , __value) => { :: peg :: RuleResult :: Matched (__newpos , Some (__value)) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , None) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , ret_type) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "=") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"=\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_expression (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , expr) => { { let __seq_res = match match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ";") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\";\"") } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , ()) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , ()) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { Rule { doc , name , ty_params , params , expr , ret_type , visibility , cached } }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , params) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "->") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"->\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = { let str_start = __pos ; match match __parse_rust_type (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , :: peg :: ParseSlice :: parse_slice (__input , str_start , __newpos)) } , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , t) => { :: peg :: RuleResult :: Matched (__pos , (|| { t }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } { :: peg :: RuleResult :: Matched (__newpos , __value) => { :: peg :: RuleResult :: Matched (__newpos , Some (__value)) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , None) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , ret_type) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "=") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"=\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_expression (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , expr) => { { let __seq_res = match match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ";") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\";\"") } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , ()) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , ()) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { Rule { doc , name , ty_params , params , expr , ret_type , visibility , cached } }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                 }
                                                                 ::peg::RuleResult::Failed => {
                                                                     ::peg::RuleResult::Failed
@@ -479,7 +480,7 @@ pub mod peg {
                                             };
                                         match __seq_res {
                                             ::peg::RuleResult::Matched(__pos, _) => {
-                                                ::peg::RuleResult::Matched(__pos, { true })
+                                                ::peg::RuleResult::Matched(__pos, (|| true)())
                                             }
                                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                         }
@@ -497,7 +498,7 @@ pub mod peg {
                 ::peg::RuleResult::Matched(__pos, __value) => {
                     ::peg::RuleResult::Matched(__pos, __value)
                 }
-                ::peg::RuleResult::Failed => ::peg::RuleResult::Matched(__pos, { false }),
+                ::peg::RuleResult::Failed => ::peg::RuleResult::Matched(__pos, (|| false)()),
             }
         }
     }
@@ -608,7 +609,7 @@ pub mod peg {
                             };
                             match __seq_res {
                                 ::peg::RuleResult::Matched(__pos, _) => {
-                                    ::peg::RuleResult::Matched(__pos, { p })
+                                    ::peg::RuleResult::Matched(__pos, (|| p)())
                                 }
                                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                             }
@@ -705,7 +706,7 @@ pub mod peg {
                                                                     _,
                                                                 ) => ::peg::RuleResult::Matched(
                                                                     __pos,
-                                                                    { RuleParamTy::Rule(r) },
+                                                                    (|| RuleParamTy::Rule(r))(),
                                                                 ),
                                                                 ::peg::RuleResult::Failed => {
                                                                     ::peg::RuleResult::Failed
@@ -760,9 +761,10 @@ pub mod peg {
                                         };
                                         match __seq_res {
                                             ::peg::RuleResult::Matched(__pos, t) => {
-                                                ::peg::RuleResult::Matched(__pos, {
-                                                    RuleParamTy::Rust(t)
-                                                })
+                                                ::peg::RuleResult::Matched(
+                                                    __pos,
+                                                    (|| RuleParamTy::Rust(t))(),
+                                                )
                                             }
                                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                         }
@@ -771,7 +773,7 @@ pub mod peg {
                             };
                             match __seq_res {
                                 ::peg::RuleResult::Matched(__pos, ty) => {
-                                    ::peg::RuleResult::Matched(__pos, { RuleParam { name, ty } })
+                                    ::peg::RuleResult::Matched(__pos, (|| RuleParam { name, ty })())
                                 }
                                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                             }
@@ -795,7 +797,7 @@ pub mod peg {
                 let __seq_res = __parse_rust_use(__input, __state, __err_state, __pos);
                 match __seq_res {
                     ::peg::RuleResult::Matched(__pos, u) => {
-                        ::peg::RuleResult::Matched(__pos, { Item::Use(u) })
+                        ::peg::RuleResult::Matched(__pos, (|| Item::Use(u))())
                     }
                     ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                 }
@@ -808,7 +810,7 @@ pub mod peg {
                     let __seq_res = __parse_peg_rule(__input, __state, __err_state, __pos);
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, r) => {
-                            ::peg::RuleResult::Matched(__pos, { Item::Rule(r) })
+                            ::peg::RuleResult::Matched(__pos, (|| Item::Rule(r))())
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
@@ -908,7 +910,7 @@ pub mod peg {
                                                                     ) => {
                                                                         ::peg::RuleResult::Matched(
                                                                             __pos,
-                                                                            {},
+                                                                            (),
                                                                         )
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
@@ -997,7 +999,7 @@ pub mod peg {
                             };
                             match __seq_res {
                                 ::peg::RuleResult::Matched(__pos, _) => {
-                                    ::peg::RuleResult::Matched(__pos, {})
+                                    ::peg::RuleResult::Matched(__pos, ())
                                 }
                                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                             }
@@ -1081,7 +1083,7 @@ pub mod peg {
                                                     let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "*") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"*\"") } ;
                                                     match __seq_res {
                                                         ::peg::RuleResult::Matched(__pos, _) => {
-                                                            ::peg::RuleResult::Matched(__pos, {})
+                                                            ::peg::RuleResult::Matched(__pos, ())
                                                         }
                                                         ::peg::RuleResult::Failed => {
                                                             ::peg::RuleResult::Failed
@@ -1127,7 +1129,7 @@ pub mod peg {
                                                                                 };
                                                                             let __step_res = {
                                                                                 let __seq_res = match __parse_IDENT (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } ;
-                                                                                match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "as") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"as\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match __parse_IDENT (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , ()) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , ()) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                                match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "as") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"as\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match __parse_IDENT (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } { :: peg :: RuleResult :: Matched (__newpos , _) => { :: peg :: RuleResult :: Matched (__newpos , ()) } , :: peg :: RuleResult :: Failed => { :: peg :: RuleResult :: Matched (__pos , ()) } , } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                             };
                                                                             match __step_res { :: peg :: RuleResult :: Matched (__newpos , __value) => { __repeat_pos = __newpos ; __repeat_value . push (__value) ; } , :: peg :: RuleResult :: Failed => { break ; } }
                                                                         }
@@ -1138,7 +1140,7 @@ pub mod peg {
                                                                             :: peg :: RuleResult :: Failed
                                                                         }
                                                                     };
-                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "}") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"}\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "}") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"}\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                 }
                                                                 ::peg::RuleResult::Failed => {
                                                                     ::peg::RuleResult::Failed
@@ -1163,7 +1165,7 @@ pub mod peg {
                                                                     _,
                                                                 ) => {
                                                                     let __seq_res = match __parse_IDENT (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } ;
-                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                    match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                 }
                                                                 ::peg::RuleResult::Failed => {
                                                                     ::peg::RuleResult::Failed
@@ -1204,7 +1206,7 @@ pub mod peg {
                                                 };
                                             match __seq_res {
                                                 ::peg::RuleResult::Matched(__pos, _) => {
-                                                    ::peg::RuleResult::Matched(__pos, {})
+                                                    ::peg::RuleResult::Matched(__pos, ())
                                                 }
                                                 ::peg::RuleResult::Failed => {
                                                     ::peg::RuleResult::Failed
@@ -1229,7 +1231,7 @@ pub mod peg {
             };
             match __seq_res {
                 ::peg::RuleResult::Matched(__pos, v) => {
-                    ::peg::RuleResult::Matched(__pos, { v.to_owned() })
+                    ::peg::RuleResult::Matched(__pos, (|| v.to_owned())())
                 }
                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
             }
@@ -1264,7 +1266,7 @@ pub mod peg {
                             };
                         match __seq_res {
                             ::peg::RuleResult::Matched(__pos, _) => {
-                                ::peg::RuleResult::Matched(__pos, {})
+                                ::peg::RuleResult::Matched(__pos, ())
                             }
                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                         }
@@ -1325,7 +1327,7 @@ pub mod peg {
                     };
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, _) => {
-                            ::peg::RuleResult::Matched(__pos, {})
+                            ::peg::RuleResult::Matched(__pos, ())
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
@@ -1418,7 +1420,7 @@ pub mod peg {
                                                 };
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                                        ::peg::RuleResult::Matched(__pos, {})
+                                                        ::peg::RuleResult::Matched(__pos, ())
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -1465,7 +1467,7 @@ pub mod peg {
                                         };
                                         match __seq_res {
                                             ::peg::RuleResult::Matched(__pos, _) => {
-                                                ::peg::RuleResult::Matched(__pos, {})
+                                                ::peg::RuleResult::Matched(__pos, ())
                                             }
                                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                         }
@@ -1507,7 +1509,7 @@ pub mod peg {
                                                 };
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                                        ::peg::RuleResult::Matched(__pos, {})
+                                                        ::peg::RuleResult::Matched(__pos, ())
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -1579,7 +1581,7 @@ pub mod peg {
                                                                         _,
                                                                     ) => {
                                                                         let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ">") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\">\"") } ;
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
                                                                         ::peg::RuleResult::Failed
@@ -1627,7 +1629,7 @@ pub mod peg {
                                                                         _,
                                                                     ) => {
                                                                         let __seq_res = match __parse_rust_type (__input , __state , __err_state , __pos) { :: peg :: RuleResult :: Matched (pos , _) => :: peg :: RuleResult :: Matched (pos , ()) , :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } ;
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
                                                                         ::peg::RuleResult::Failed
@@ -1668,7 +1670,7 @@ pub mod peg {
                                                                             }
                                                                             :: peg :: RuleResult :: Matched (__repeat_pos , ())
                                                                         };
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
                                                                         ::peg::RuleResult::Failed
@@ -1747,13 +1749,16 @@ pub mod peg {
                 }
             };
             match __seq_res {
-                ::peg::RuleResult::Matched(__pos, s) => ::peg::RuleResult::Matched(__pos, {
-                    if s.len() == 1 {
-                        s.into_iter().next().unwrap()
-                    } else {
-                        ChoiceExpr(s)
-                    }
-                }),
+                ::peg::RuleResult::Matched(__pos, s) => ::peg::RuleResult::Matched(
+                    __pos,
+                    (|| {
+                        if s.len() == 1 {
+                            s.into_iter().next().unwrap()
+                        } else {
+                            ChoiceExpr(s)
+                        }
+                    })(),
+                ),
                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
             }
         }
@@ -1786,87 +1791,26 @@ pub mod peg {
             };
             match __seq_res {
                 ::peg::RuleResult::Matched(__pos, elements) => {
-                    let __seq_res = match __parse_code_block(__input, __state, __err_state, __pos) {
+                    let __seq_res = match __parse_BRACE_GROUP(__input, __state, __err_state, __pos)
+                    {
                         ::peg::RuleResult::Matched(__newpos, __value) => {
                             ::peg::RuleResult::Matched(__newpos, Some(__value))
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Matched(__pos, None),
                     };
                     match __seq_res {
-                        ::peg::RuleResult::Matched(__pos, code) => {
-                            ::peg::RuleResult::Matched(__pos, {
+                        ::peg::RuleResult::Matched(__pos, code) => ::peg::RuleResult::Matched(
+                            __pos,
+                            (|| {
                                 if let Some(code) = code {
-                                    ActionExpr(elements, Some(code.1), code.0)
+                                    ActionExpr(elements, Some(code))
                                 } else if elements.len() != 1 {
-                                    ActionExpr(elements, None, false)
+                                    ActionExpr(elements, None)
                                 } else {
                                     elements.into_iter().next().unwrap().expr
                                 }
-                            })
-                        }
-                        ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
-                    }
-                }
-                ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
-            }
-        }
-    }
-    fn __parse_code_block<'input>(
-        __input: &'input Input,
-        __state: &mut ParseState<'input>,
-        __err_state: &mut ::peg::error::ErrorState,
-        __pos: usize,
-    ) -> ::peg::RuleResult<(bool, TokenStream)> {
-        #![allow(non_snake_case, unused)]
-        {
-            let __seq_res = match ::peg::ParseLiteral::parse_string_literal(__input, __pos, "{") {
-                ::peg::RuleResult::Matched(__pos, __val) => {
-                    ::peg::RuleResult::Matched(__pos, __val)
-                }
-                ::peg::RuleResult::Failed => __err_state.mark_failure(__pos, "\"{\""),
-            };
-            match __seq_res {
-                ::peg::RuleResult::Matched(__pos, _) => {
-                    let __seq_res = match match ::peg::ParseLiteral::parse_string_literal(
-                        __input, __pos, "?",
-                    ) {
-                        ::peg::RuleResult::Matched(__pos, __val) => {
-                            ::peg::RuleResult::Matched(__pos, __val)
-                        }
-                        ::peg::RuleResult::Failed => __err_state.mark_failure(__pos, "\"?\""),
-                    } {
-                        ::peg::RuleResult::Matched(__newpos, __value) => {
-                            ::peg::RuleResult::Matched(__newpos, Some(__value))
-                        }
-                        ::peg::RuleResult::Failed => ::peg::RuleResult::Matched(__pos, None),
-                    };
-                    match __seq_res {
-                        ::peg::RuleResult::Matched(__pos, is_cond) => {
-                            let __seq_res = __input.group_body(__pos);
-                            match __seq_res {
-                                ::peg::RuleResult::Matched(__pos, code) => {
-                                    let __seq_res = match ::peg::ParseLiteral::parse_string_literal(
-                                        __input, __pos, "}",
-                                    ) {
-                                        ::peg::RuleResult::Matched(__pos, __val) => {
-                                            ::peg::RuleResult::Matched(__pos, __val)
-                                        }
-                                        ::peg::RuleResult::Failed => {
-                                            __err_state.mark_failure(__pos, "\"}\"")
-                                        }
-                                    };
-                                    match __seq_res {
-                                        ::peg::RuleResult::Matched(__pos, _) => {
-                                            ::peg::RuleResult::Matched(__pos, {
-                                                (is_cond.is_some(), code)
-                                            })
-                                        }
-                                        ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
-                                    }
-                                }
-                                ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
-                            }
-                        }
+                            })(),
+                        ),
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
                 }
@@ -1897,7 +1841,7 @@ pub mod peg {
                             };
                         match __seq_res {
                             ::peg::RuleResult::Matched(__pos, _) => {
-                                ::peg::RuleResult::Matched(__pos, { l })
+                                ::peg::RuleResult::Matched(__pos, (|| l)())
                             }
                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                         }
@@ -1915,12 +1859,13 @@ pub mod peg {
                     let __seq_res = __parse_suffixed(__input, __state, __err_state, __pos);
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, expression) => {
-                            ::peg::RuleResult::Matched(__pos, {
-                                TaggedExpr {
+                            ::peg::RuleResult::Matched(
+                                __pos,
+                                (|| TaggedExpr {
                                     name: label,
                                     expr: expression,
-                                }
-                            })
+                                })(),
+                            )
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
@@ -1952,7 +1897,7 @@ pub mod peg {
                             };
                         match __seq_res {
                             ::peg::RuleResult::Matched(__pos, _) => {
-                                ::peg::RuleResult::Matched(__pos, { OptionalExpr(Box::new(e)) })
+                                ::peg::RuleResult::Matched(__pos, (|| OptionalExpr(Box::new(e)))())
                             }
                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                         }
@@ -1997,13 +1942,17 @@ pub mod peg {
                                                 );
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, sep) => {
-                                                        ::peg::RuleResult::Matched(__pos, {
-                                                            Repeat(
-                                                                Box::new(e),
-                                                                count,
-                                                                Some(Box::new(sep)),
-                                                            )
-                                                        })
+                                                        ::peg::RuleResult::Matched(
+                                                            __pos,
+                                                            (|| {
+                                                                Repeat(
+                                                                    Box::new(e),
+                                                                    count,
+                                                                    Some(Box::new(sep)),
+                                                                )
+                                                            })(
+                                                            ),
+                                                        )
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -2050,13 +1999,17 @@ pub mod peg {
                                                 );
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, sep) => {
-                                                        ::peg::RuleResult::Matched(__pos, {
-                                                            Repeat(
-                                                                Box::new(e),
-                                                                BoundedRepeat::Plus,
-                                                                Some(Box::new(sep)),
-                                                            )
-                                                        })
+                                                        ::peg::RuleResult::Matched(
+                                                            __pos,
+                                                            (|| {
+                                                                Repeat(
+                                                                    Box::new(e),
+                                                                    BoundedRepeat::Plus,
+                                                                    Some(Box::new(sep)),
+                                                                )
+                                                            })(
+                                                            ),
+                                                        )
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -2105,11 +2058,13 @@ pub mod peg {
                                                             ::peg::RuleResult::Matched(
                                                                 __pos,
                                                                 count,
-                                                            ) => {
-                                                                ::peg::RuleResult::Matched(__pos, {
+                                                            ) => ::peg::RuleResult::Matched(
+                                                                __pos,
+                                                                (|| {
                                                                     Repeat(Box::new(e), count, None)
-                                                                })
-                                                            }
+                                                                })(
+                                                                ),
+                                                            ),
                                                             ::peg::RuleResult::Failed => {
                                                                 ::peg::RuleResult::Failed
                                                             }
@@ -2142,15 +2097,17 @@ pub mod peg {
                                                             ::peg::RuleResult::Matched(
                                                                 __pos,
                                                                 _,
-                                                            ) => {
-                                                                ::peg::RuleResult::Matched(__pos, {
+                                                            ) => ::peg::RuleResult::Matched(
+                                                                __pos,
+                                                                (|| {
                                                                     Repeat(
                                                                         Box::new(e),
                                                                         BoundedRepeat::Plus,
                                                                         None,
                                                                     )
-                                                                })
-                                                            }
+                                                                })(
+                                                                ),
+                                                            ),
                                                             ::peg::RuleResult::Failed => {
                                                                 ::peg::RuleResult::Failed
                                                             }
@@ -2215,9 +2172,10 @@ pub mod peg {
                                 };
                                 match __seq_res {
                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                        ::peg::RuleResult::Matched(__pos, {
-                                            BoundedRepeat::Exact(n)
-                                        })
+                                        ::peg::RuleResult::Matched(
+                                            __pos,
+                                            (|| BoundedRepeat::Exact(n))(),
+                                        )
                                     }
                                     ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                 }
@@ -2293,11 +2251,11 @@ pub mod peg {
                                                             ::peg::RuleResult::Matched(
                                                                 __pos,
                                                                 _,
-                                                            ) => {
-                                                                ::peg::RuleResult::Matched(__pos, {
-                                                                    BoundedRepeat::Both(min, max)
-                                                                })
-                                                            }
+                                                            ) => ::peg::RuleResult::Matched(
+                                                                __pos,
+                                                                (|| BoundedRepeat::Both(min, max))(
+                                                                ),
+                                                            ),
                                                             ::peg::RuleResult::Failed => {
                                                                 ::peg::RuleResult::Failed
                                                             }
@@ -2322,7 +2280,7 @@ pub mod peg {
                             ::peg::RuleResult::Matched(__pos, __value)
                         }
                         ::peg::RuleResult::Failed => {
-                            ::peg::RuleResult::Matched(__pos, { BoundedRepeat::None })
+                            ::peg::RuleResult::Matched(__pos, (|| BoundedRepeat::None)())
                         }
                     }
                 }
@@ -2386,9 +2344,10 @@ pub mod peg {
                         let __seq_res = __parse_primary(__input, __state, __err_state, __pos);
                         match __seq_res {
                             ::peg::RuleResult::Matched(__pos, expression) => {
-                                ::peg::RuleResult::Matched(__pos, {
-                                    MatchStrExpr(Box::new(expression))
-                                })
+                                ::peg::RuleResult::Matched(
+                                    __pos,
+                                    (|| MatchStrExpr(Box::new(expression)))(),
+                                )
                             }
                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                         }
@@ -2417,9 +2376,10 @@ pub mod peg {
                                     __parse_primary(__input, __state, __err_state, __pos);
                                 match __seq_res {
                                     ::peg::RuleResult::Matched(__pos, expression) => {
-                                        ::peg::RuleResult::Matched(__pos, {
-                                            PosAssertExpr(Box::new(expression))
-                                        })
+                                        ::peg::RuleResult::Matched(
+                                            __pos,
+                                            (|| PosAssertExpr(Box::new(expression)))(),
+                                        )
                                     }
                                     ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                 }
@@ -2449,9 +2409,10 @@ pub mod peg {
                                             __parse_primary(__input, __state, __err_state, __pos);
                                         match __seq_res {
                                             ::peg::RuleResult::Matched(__pos, expression) => {
-                                                ::peg::RuleResult::Matched(__pos, {
-                                                    NegAssertExpr(Box::new(expression))
-                                                })
+                                                ::peg::RuleResult::Matched(
+                                                    __pos,
+                                                    (|| NegAssertExpr(Box::new(expression)))(),
+                                                )
                                             }
                                             ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                         }
@@ -2574,9 +2535,11 @@ pub mod peg {
                                                     };
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                                        ::peg::RuleResult::Matched(__pos, {
-                                                            PrecedenceExpr { levels: levels }
-                                                        })
+                                                        ::peg::RuleResult::Matched(
+                                                            __pos,
+                                                            (|| PrecedenceExpr { levels: levels })(
+                                                            ),
+                                                        )
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -2654,9 +2617,10 @@ pub mod peg {
                                                     };
                                                 match __seq_res {
                                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                                        ::peg::RuleResult::Matched(__pos, {
-                                                            PositionExpr
-                                                        })
+                                                        ::peg::RuleResult::Matched(
+                                                            __pos,
+                                                            (|| PositionExpr)(),
+                                                        )
                                                     }
                                                     ::peg::RuleResult::Failed => {
                                                         ::peg::RuleResult::Failed
@@ -2738,11 +2702,12 @@ pub mod peg {
                                                                     ) => {
                                                                         ::peg::RuleResult::Matched(
                                                                             __pos,
-                                                                            {
+                                                                            (|| {
                                                                                 QuietExpr(Box::new(
                                                                                     e,
                                                                                 ))
-                                                                            },
+                                                                            })(
+                                                                            ),
                                                                         )
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
@@ -2819,7 +2784,7 @@ pub mod peg {
                                                                         s,
                                                                     ) => {
                                                                         let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ;
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { FailExpr (s) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { FailExpr (s) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
                                                                         ::peg::RuleResult::Failed
@@ -2886,11 +2851,10 @@ pub mod peg {
                                                             ::peg::RuleResult::Matched(
                                                                 __pos,
                                                                 name,
-                                                            ) => {
-                                                                ::peg::RuleResult::Matched(__pos, {
-                                                                    RuleExpr(name, Vec::new())
-                                                                })
-                                                            }
+                                                            ) => ::peg::RuleResult::Matched(
+                                                                __pos,
+                                                                (|| RuleExpr(name, Vec::new()))(),
+                                                            ),
                                                             ::peg::RuleResult::Failed => {
                                                                 ::peg::RuleResult::Failed
                                                             }
@@ -2938,7 +2902,7 @@ pub mod peg {
                                                                             }
                                                                             :: peg :: RuleResult :: Matched (__repeat_pos , __repeat_value)
                                                                         };
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , args) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { RuleExpr (name , args) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , args) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { RuleExpr (name , args) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
                                                                         ::peg::RuleResult::Failed
@@ -2972,7 +2936,7 @@ pub mod peg {
                                                                     ) => {
                                                                         ::peg::RuleResult::Matched(
                                                                             __pos,
-                                                                            { LiteralExpr(l) },
+                                                                            (|| LiteralExpr(l))(),
                                                                         )
                                                                     }
                                                                     ::peg::RuleResult::Failed => {
@@ -2996,9 +2960,9 @@ pub mod peg {
                                                                                 __err_state,
                                                                                 __pos,
                                                                             );
-                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , p) => { :: peg :: RuleResult :: Matched (__pos , { PatternExpr (p) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
+                                                                        match __seq_res { :: peg :: RuleResult :: Matched (__pos , p) => { :: peg :: RuleResult :: Matched (__pos , (|| { PatternExpr (p) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , }
                                                                     };
-                                                                    match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "(") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"(\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "@") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"@\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { MarkerExpr (true) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "@") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"@\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { MarkerExpr (false) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "##") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"##\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_IDENT (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , method) => { { let __seq_res = __parse_PAREN_GROUP (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , args) => { :: peg :: RuleResult :: Matched (__pos , { MethodExpr (method , args) }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "(") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"(\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_expression (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , expression) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , { expression }) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } } } } } } }
+                                                                    match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "(") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"(\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "@") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"@\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { MarkerExpr (true) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "@") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"@\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { MarkerExpr (false) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __choice_res = { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "##") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"##\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_IDENT (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , method) => { { let __seq_res = __parse_PAREN_GROUP (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , args) => { :: peg :: RuleResult :: Matched (__pos , (|| { MethodExpr (method , args . stream ()) }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } ; match __choice_res { :: peg :: RuleResult :: Matched (__pos , __value) => :: peg :: RuleResult :: Matched (__pos , __value) , :: peg :: RuleResult :: Failed => { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , "(") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\"(\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { { let __seq_res = __parse_expression (__input , __state , __err_state , __pos) ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , expression) => { { let __seq_res = match :: peg :: ParseLiteral :: parse_string_literal (__input , __pos , ")") { :: peg :: RuleResult :: Matched (__pos , __val) => :: peg :: RuleResult :: Matched (__pos , __val) , :: peg :: RuleResult :: Failed => __err_state . mark_failure (__pos , "\")\"") } ; match __seq_res { :: peg :: RuleResult :: Matched (__pos , _) => { :: peg :: RuleResult :: Matched (__pos , (|| { expression }) ()) } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } :: peg :: RuleResult :: Failed => :: peg :: RuleResult :: Failed , } } } } } } } } }
                                                                 }
                                                             }
                                                         }
@@ -3050,7 +3014,7 @@ pub mod peg {
                                 };
                                 match __seq_res {
                                     ::peg::RuleResult::Matched(__pos, _) => {
-                                        ::peg::RuleResult::Matched(__pos, { RuleArg::Peg(e) })
+                                        ::peg::RuleResult::Matched(__pos, (|| RuleArg::Peg(e))())
                                     }
                                     ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                                 }
@@ -3120,7 +3084,7 @@ pub mod peg {
                     };
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, tt) => {
-                            ::peg::RuleResult::Matched(__pos, { RuleArg::Rust(tt) })
+                            ::peg::RuleResult::Matched(__pos, (|| RuleArg::Rust(tt))())
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
@@ -3159,13 +3123,12 @@ pub mod peg {
                 }
             };
             match __seq_res {
-                ::peg::RuleResult::Matched(__pos, operators) => {
-                    ::peg::RuleResult::Matched(__pos, {
-                        PrecedenceLevel {
-                            operators: operators,
-                        }
-                    })
-                }
+                ::peg::RuleResult::Matched(__pos, operators) => ::peg::RuleResult::Matched(
+                    __pos,
+                    (|| PrecedenceLevel {
+                        operators: operators,
+                    })(),
+                ),
                 ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
             }
         }
@@ -3200,11 +3163,10 @@ pub mod peg {
                 ::peg::RuleResult::Matched(__pos, elements) => {
                     let __seq_res = __parse_BRACE_GROUP(__input, __state, __err_state, __pos);
                     match __seq_res {
-                        ::peg::RuleResult::Matched(__pos, action) => {
-                            ::peg::RuleResult::Matched(__pos, {
-                                PrecedenceOperator { elements, action }
-                            })
-                        }
+                        ::peg::RuleResult::Matched(__pos, action) => ::peg::RuleResult::Matched(
+                            __pos,
+                            (|| PrecedenceOperator { elements, action })(),
+                        ),
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
                 }
@@ -3322,7 +3284,7 @@ pub mod peg {
                     let __seq_res = __input.ident(__pos);
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, i) => {
-                            ::peg::RuleResult::Matched(__pos, { i })
+                            ::peg::RuleResult::Matched(__pos, (|| i)())
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
@@ -3345,7 +3307,7 @@ pub mod peg {
         __state: &mut ParseState<'input>,
         __err_state: &mut ::peg::error::ErrorState,
         __pos: usize,
-    ) -> ::peg::RuleResult<TokenStream> {
+    ) -> ::peg::RuleResult<Group> {
         #![allow(non_snake_case, unused)]
         __input.group(__pos, Delimiter::Parenthesis)
     }
@@ -3354,7 +3316,7 @@ pub mod peg {
         __state: &mut ParseState<'input>,
         __err_state: &mut ::peg::error::ErrorState,
         __pos: usize,
-    ) -> ::peg::RuleResult<TokenStream> {
+    ) -> ::peg::RuleResult<Group> {
         #![allow(non_snake_case, unused)]
         __input.group(__pos, Delimiter::Brace)
     }
@@ -3363,7 +3325,7 @@ pub mod peg {
         __state: &mut ParseState<'input>,
         __err_state: &mut ::peg::error::ErrorState,
         __pos: usize,
-    ) -> ::peg::RuleResult<TokenStream> {
+    ) -> ::peg::RuleResult<Group> {
         #![allow(non_snake_case, unused)]
         __input.group(__pos, Delimiter::Bracket)
     }
@@ -3389,7 +3351,7 @@ pub mod peg {
                     };
                     match __seq_res {
                         ::peg::RuleResult::Matched(__pos, _) => {
-                            ::peg::RuleResult::Matched(__pos, {})
+                            ::peg::RuleResult::Matched(__pos, ())
                         }
                         ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
diff --git a/peg-macros/grammar.rustpeg b/peg-macros/grammar.rustpeg
index 8664b71..8d922b0 100644
--- a/peg-macros/grammar.rustpeg
+++ b/peg-macros/grammar.rustpeg
@@ -3,7 +3,7 @@ pub grammar peg() for FlatTokenStream {
 use crate::ast::*;
 use crate::ast::Expr::*;
 use crate::tokens::FlatTokenStream;
-use proc_macro2::{ TokenStream, Ident, Literal, Delimiter };
+use proc_macro2::{ TokenStream, Ident, Group, 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()* "}"
@@ -67,19 +67,16 @@ rule choice() -> Expr = s:sequence() ++ "/" {
 }
 
 rule sequence() -> Expr
-     = elements:labeled()* code:code_block()? {
+     = elements:labeled()* code:BRACE_GROUP()? {
          if let Some(code) = code {
-            ActionExpr(elements, Some(code.1), code.0)
+            ActionExpr(elements, Some(code))
          } else if elements.len() != 1 {
-             ActionExpr(elements, None, false)
+             ActionExpr(elements, None)
          } 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 } }
@@ -117,7 +114,7 @@ rule primary() -> Expr
   / p:BRACKET_GROUP() { PatternExpr(p) }
   / "(" "@" ")" { MarkerExpr(true) }
   / "@" { MarkerExpr(false) }
-  / "##" method:IDENT() args:PAREN_GROUP() { MethodExpr(method, args) }
+  / "##" method:IDENT() args:PAREN_GROUP() { MethodExpr(method, args.stream()) }
   / "(" expression:expression() ")" { expression }
 
     rule rule_arg() -> RuleArg
@@ -135,9 +132,9 @@ rule precedence_op() -> PrecedenceOperator
 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 PAREN_GROUP()   -> Group = ##group(Delimiter::Parenthesis)
+rule BRACE_GROUP()   -> Group = ##group(Delimiter::Brace)
+rule BRACKET_GROUP() -> Group = ##group(Delimiter::Bracket)
 rule LIFETIME() = "'" IDENT()
 rule INTEGER() = LITERAL()
 
diff --git a/peg-macros/tokens.rs b/peg-macros/tokens.rs
index bb59935..3a76477 100644
--- a/peg-macros/tokens.rs
+++ b/peg-macros/tokens.rs
@@ -64,33 +64,14 @@ impl FlatTokenStream {
         }
     }
 
-    pub fn group(&self, pos: usize, delim: Delimiter) -> RuleResult<TokenStream> {
+    pub fn group(&self, pos: usize, delim: Delimiter) -> RuleResult<Group> {
         match self.tokens.get(pos) {
             Some(Token::Begin(g, n)) if g.delimiter() == delim => {
-                RuleResult::Matched(*n, g.stream())
+                RuleResult::Matched(*n, g.clone())
             }
             _ => RuleResult::Failed,
         }
     }
-
-    pub fn group_body(&self, mut pos: usize) -> RuleResult<TokenStream> {
-        let mut r: Vec<TokenTree> = Vec::new();
-        while let Some(t) = self.tokens.get(pos) {
-            match t {
-                Token::Ident(i) => r.push(i.clone().into()),
-                Token::Literal(i) => r.push(i.clone().into()),
-                Token::Punct(i) => r.push(i.clone().into()),
-                Token::Begin(g, n) => {
-                    r.push(g.clone().into());
-                    pos = *n;
-                    continue;
-                }
-                Token::End(..) => break,
-            }
-            pos += 1;
-        }
-        RuleResult::Matched(pos, r.into_iter().collect())
-    }
 }
 
 #[derive(Debug, Clone)]
diff --git a/peg-macros/translate.rs b/peg-macros/translate.rs
index 82e3ec2..cbb5db4 100644
--- a/peg-macros/translate.rs
+++ b/peg-macros/translate.rs
@@ -1,4 +1,4 @@
-use proc_macro2::{Ident, Span, TokenStream};
+use proc_macro2::{Group, Ident, Span, TokenStream, TokenTree};
 use std::collections::{HashMap, HashSet};
 
 use quote::{format_ident, quote, quote_spanned};
@@ -16,6 +16,17 @@ pub fn report_error_expr(span: Span, msg: String) -> TokenStream {
     quote_spanned!(span=> { compile_error!(#msg); panic!() })
 }
 
+/// Test if the group begins with a specific marker character, and if so, return the remaining tokens.
+fn group_check_prefix(group: &Group, prefix: char) -> Option<TokenStream> {
+    let mut iter = group.stream().into_iter();
+    match iter.next() {
+        Some(TokenTree::Punct(p)) if p.as_char() == prefix => {
+            Some(iter.collect())
+        }
+        _ => None
+    }
+}
+
 fn extra_args_def(grammar: &Grammar) -> TokenStream {
     let args: Vec<TokenStream> = grammar
         .args
@@ -351,8 +362,9 @@ fn compile_expr(context: &Context, e: &Expr, result_used: bool) -> TokenStream {
             }}
         }
 
-        PatternExpr(ref pattern) => {
+        PatternExpr(ref pattern_group) => {
             let invert = false;
+            let pattern = pattern_group.stream();
             let pat_str = pattern.to_string();
 
             let (in_set, not_in_set) = cond_swap(
@@ -610,19 +622,24 @@ fn compile_expr(context: &Context, e: &Expr, result_used: bool) -> TokenStream {
             }}
         }
 
-        ActionExpr(ref exprs, ref code, is_cond) => labeled_seq(context, &exprs, {
-            if *is_cond {
-                quote! {
-                    match { #code } {
-                        Ok(res) => ::peg::RuleResult::Matched(__pos, res),
-                        Err(expected) => {
-                            __err_state.mark_failure(__pos, expected);
-                            ::peg::RuleResult::Failed
-                        },
+        ActionExpr(ref exprs, ref code) => labeled_seq(context, &exprs, {
+            if let Some(code) = code {
+                // Peek and see if the first token in the block is '?'. If so, it's a conditional block
+                if let Some(body) = group_check_prefix(&code, '?') {
+                    quote_spanned!{code.span() =>
+                        match (||{ #body })() {
+                            Ok(res) => ::peg::RuleResult::Matched(__pos, res),
+                            Err(expected) => {
+                                __err_state.mark_failure(__pos, expected);
+                                ::peg::RuleResult::Failed
+                            },
+                        }
                     }
+                } else {
+                    quote_spanned!{code.span() => ::peg::RuleResult::Matched(__pos, (||#code)()) }
                 }
             } else {
-                quote! { ::peg::RuleResult::Matched(__pos, { #code }) }
+                quote!(::peg::RuleResult::Matched(__pos, ()))
             }
         }),
         MatchStrExpr(ref expr) => {
@@ -654,7 +671,7 @@ fn compile_expr(context: &Context, e: &Expr, result_used: bool) -> TokenStream {
         PrecedenceExpr { ref levels } => {
             let mut pre_rules = Vec::new();
             let mut level_code = Vec::new();
-            let mut span_capture = None;
+            let mut span_capture: Option<(TokenStream, TokenStream, TokenStream, &Group)> = None;
 
             for (prec, level) in levels.iter().enumerate() {
                 let prec = prec as i32;
@@ -673,12 +690,14 @@ fn compile_expr(context: &Context, e: &Expr, result_used: bool) -> TokenStream {
                     let r_arg = name_or_ignore(right_arg.name.as_ref());
 
                     let action = &op.action;
+                    let action = quote_spanned!(op.action.span()=>(||#action)());
+
                     let action = if let Some((lpos_name, val_name, rpos_name, wrap_action)) =
                         &span_capture
                     {
-                        quote!((|#lpos_name, #val_name, #rpos_name| {#wrap_action})(__lpos, #action, __pos))
+                        quote_spanned!(wrap_action.span()=> (|#lpos_name, #val_name, #rpos_name|#wrap_action)(__lpos, #action, __pos))
                     } else {
-                        quote!({#action})
+                        action
                     };
 
                     match (&left_arg.expr, &right_arg.expr) {


Test patch:
diff --git a/tests/compile-fail/rust_action_type_error.stderr b/tests/compile-fail/rust_action_type_error.stderr
index 75dea4e..732d5dd 100644
--- a/tests/compile-fail/rust_action_type_error.stderr
+++ b/tests/compile-fail/rust_action_type_error.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
- --> $DIR/rust_action_type_error.rs:7:29
+ --> $DIR/rust_action_type_error.rs:7:27
   |
 7 |     rule foo() -> X = "a" { Y } //~ ERROR
-  |                             ^ expected struct `X`, found struct `Y`
+  |                           ^^^^^ expected struct `X`, found struct `Y`
diff --git a/tests/run-pass/conditional_block.rs b/tests/run-pass/conditional_block.rs
index 67e58dd..9383fb7 100644
--- a/tests/run-pass/conditional_block.rs
+++ b/tests/run-pass/conditional_block.rs
@@ -28,6 +28,13 @@ peg::parser!( grammar parse() for str {
             }
         }
 
+    pub rule return_early() -> i32 = vs:$([_]+) {?
+        let v = vs.parse::<i32>().map_err(|_| "number")?;
+        if v > 100 {
+            return Err("smaller number");
+        }
+        Ok(v)
+    }
 });
 
 fn main() {
@@ -41,4 +48,8 @@ fn main() {
     assert!(parse::xml("<a><b></b><c></c></a>").is_ok());
     assert!(parse::xml("<a><b><c></b></c></a>").is_err());
     assert!(parse::xml("<a><b></c><c></b></a>").is_err());
+
+    assert!(parse::return_early("a").unwrap_err().expected.tokens().any(|e| e == "number"));
+    assert!(parse::return_early("123").unwrap_err().expected.tokens().any(|e| e == "smaller number"));
+    assert_eq!(parse::return_early("99").unwrap(), 99);
 }