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

Issue:
Cannot `use crate::types::*` in parser mod in 0.6
i have some code like this:

```rust
peg::parser!{
    pub grammar my_parser() for [u8] {
        use peg::ParseLiteral;
        use crate::types::MyStruct;

        rule some_rule() -> MyStruct<'input>
            = // ... something
```

the problem is with the use declaration: as "crate" is a reserved identifier, it is not allowed by the `IDENT()` rule in [grammar.rustpeg](https://github.com/kevinmehall/rust-peg/blob/master/peg-macros/grammar.rustpeg#L46), and so i get a not-so-helpful error message
```
error: expected one of "#", "crate", "pub", "rule", "}"
  --> src/parser.rs:15:9
   |
15 |         use crate::types::MyStruct;
   |         ^^^
```

i think this could be fixed by extending the `rust_path` rule to allow "crate" as first component of the path. i'll prepare a pull request soon.


Discussion / hints:
update: i'm not sure how to test things.. but the way i imagine it to work would be something like this (cut out of `grammar.rustpeg`):

```
use peg::parser;

parser!{
  pub grammar rust_path_parser() for str {
    pub rule capture_rust_path() -> &'input str
      = p:$(rust_path()) { p }

    rule rust_path()
      = "crate::" IDENT() ++ "::"
      / IDENT() ++ "::"

    rule KEYWORD() = "pub" / "crate" / "rule" / "use" / "type"
    rule IDENT() = !KEYWORD() ['a' ..= 'z']+ // this is a simplified ident rule for testing..
  }
}

pub fn main() {
    assert_eq!(rust_path_parser::capture_rust_path("crate::foo::bar"), Ok("crate::foo::bar"));
}
```

but i'm not sure how to make rustpeg use the updated `peg-macros/grammar.rustpeg` for interpreting peg grammars; `cargo clean` and `cargo build` didn't seem to have an effect; or i'm having another error somewhere..

Fix patch:
diff --git a/peg-macros/grammar.rs b/peg-macros/grammar.rs
index 53757ae..471cf07 100644
--- a/peg-macros/grammar.rs
+++ b/peg-macros/grammar.rs
@@ -1214,43 +1214,94 @@ pub mod peg {
     ) -> ::peg::RuleResult<()> {
         #![allow(non_snake_case, unused)]
         {
-            let mut __repeat_pos = __pos;
-            let mut __repeat_value = vec![];
-            loop {
-                let __pos = __repeat_pos;
-                let __pos = if __repeat_value.is_empty() {
-                    __pos
-                } else {
-                    let __sep_res =
-                        match ::peg::ParseLiteral::parse_string_literal(__input, __pos, "::") {
-                            ::peg::RuleResult::Matched(__pos, __val) => {
-                                ::peg::RuleResult::Matched(__pos, __val)
+            let __seq_res = match {
+                let __seq_res =
+                    match ::peg::ParseLiteral::parse_string_literal(__input, __pos, "crate") {
+                        ::peg::RuleResult::Matched(__pos, __val) => {
+                            ::peg::RuleResult::Matched(__pos, __val)
+                        }
+                        ::peg::RuleResult::Failed => __err_state.mark_failure(__pos, "\"crate\""),
+                    };
+                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 => __err_state.mark_failure(__pos, "\"::\""),
-                        };
-                    match __sep_res {
-                        ::peg::RuleResult::Matched(__newpos, _) => __newpos,
-                        ::peg::RuleResult::Failed => break,
+                            ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
+                        }
                     }
-                };
-                let __step_res = match __parse_IDENT(__input, __state, __err_state, __pos) {
-                    ::peg::RuleResult::Matched(pos, _) => ::peg::RuleResult::Matched(pos, ()),
                     ::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;
+                }
+            } {
+                ::peg::RuleResult::Matched(__newpos, _) => ::peg::RuleResult::Matched(__newpos, ()),
+                ::peg::RuleResult::Failed => ::peg::RuleResult::Matched(__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 __pos = if __repeat_value.is_empty() {
+                                __pos
+                            } else {
+                                let __sep_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 __sep_res {
+                                    ::peg::RuleResult::Matched(__newpos, _) => __newpos,
+                                    ::peg::RuleResult::Failed => break,
+                                }
+                            };
+                            let __step_res =
+                                match __parse_IDENT(__input, __state, __err_state, __pos) {
+                                    ::peg::RuleResult::Matched(pos, _) => {
+                                        ::peg::RuleResult::Matched(pos, ())
+                                    }
+                                    ::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;
+                                }
+                            }
+                        }
+                        if __repeat_value.len() >= 1 {
+                            ::peg::RuleResult::Matched(__repeat_pos, ())
+                        } else {
+                            ::peg::RuleResult::Failed
+                        }
+                    };
+                    match __seq_res {
+                        ::peg::RuleResult::Matched(__pos, _) => {
+                            ::peg::RuleResult::Matched(__pos, {})
+                        }
+                        ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
                     }
                 }
-            }
-            if __repeat_value.len() >= 1 {
-                ::peg::RuleResult::Matched(__repeat_pos, ())
-            } else {
-                ::peg::RuleResult::Failed
+                ::peg::RuleResult::Failed => ::peg::RuleResult::Failed,
             }
         }
     }
diff --git a/peg-macros/grammar.rustpeg b/peg-macros/grammar.rustpeg
index b2e2b00..d0a3b52 100644
--- a/peg-macros/grammar.rustpeg
+++ b/peg-macros/grammar.rustpeg
@@ -43,7 +43,8 @@ rule rust_use() -> TokenStream
         / ("as" IDENT())?
     ) ";") { v.to_owned() }
 
-rule rust_path() = IDENT() ++ "::"
+rule rust_path()
+    = ("crate" "::")? IDENT() ++ "::"
 
 rule rust_type()
     = BRACKET_GROUP()


Test patch:
diff --git a/tests/run-pass/crate_import.rs b/tests/run-pass/crate_import.rs
new file mode 100644
index 0000000..fbdd3fc
--- /dev/null
+++ b/tests/run-pass/crate_import.rs
@@ -0,0 +1,20 @@
+extern crate peg;
+
+peg::parser!{
+    pub grammar foo_parser() for str {
+        use crate::types::Foo;
+
+        pub rule foo() -> Foo
+            = "foo" { Foo }
+    }
+}
+
+mod types {
+    #[derive(PartialEq, Debug)]
+    pub struct Foo;
+}
+
+
+fn main() {
+    assert_eq!(foo_parser::foo("foo"), Ok(crate::types::Foo));
+}