From d8889528df7b259a092485c9a1ed32d4411cef77 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Sun, 2 Jun 2024 17:36:59 -0600 Subject: [PATCH] Don't panic on parse error at EOF in macro grammar Fixes #376 --- peg-macros/lib.rs | 7 ++++++- peg-macros/tokens.rs | 7 ++++++- tests/compile-fail/incomplete_grammar.rs | 8 ++++++++ tests/compile-fail/incomplete_grammar.stderr | 17 +++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/compile-fail/incomplete_grammar.rs create mode 100644 tests/compile-fail/incomplete_grammar.stderr diff --git a/peg-macros/lib.rs b/peg-macros/lib.rs index 6393788..4d2e131 100644 --- a/peg-macros/lib.rs +++ b/peg-macros/lib.rs @@ -2,6 +2,7 @@ extern crate proc_macro; extern crate proc_macro2; extern crate quote; +use peg::Parse; use quote::quote_spanned; // This can't use the `peg` crate as it would be a circular dependency, but the generated code in grammar.rs @@ -23,7 +24,11 @@ pub fn parser(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let grammar = match grammar::peg::peg_grammar(&tokens) { Ok(g) => g, Err(err) => { - let msg = format!("expected {}", err.expected); + let msg = if tokens.is_eof(err.location.1) { + format!("expected {} at end of input", err.expected) + } else { + format!("expected {}", err.expected) + }; return quote_spanned!(err.location.0=> compile_error!(#msg);).into(); } }; diff --git a/peg-macros/tokens.rs b/peg-macros/tokens.rs index 3ca6139..c727f0b 100644 --- a/peg-macros/tokens.rs +++ b/peg-macros/tokens.rs @@ -122,7 +122,12 @@ impl Parse for FlatTokenStream { } fn position_repr(&self, pos: usize) -> Sp { - Sp(self.tokens[pos].span(), pos) + let span = self.tokens.get(pos) + .map_or_else( + || Span::call_site(), + |t| t.span() + ); + Sp(span, pos) } } diff --git a/tests/compile-fail/incomplete_grammar.rs b/tests/compile-fail/incomplete_grammar.rs new file mode 100644 index 0000000..e42cc8d --- /dev/null +++ b/tests/compile-fail/incomplete_grammar.rs @@ -0,0 +1,8 @@ + +peg::parser!(); + +peg::parser!( + grammar parser() for str +); + +fn main() {} \ No newline at end of file diff --git a/tests/compile-fail/incomplete_grammar.stderr b/tests/compile-fail/incomplete_grammar.stderr new file mode 100644 index 0000000..12f7a7e --- /dev/null +++ b/tests/compile-fail/incomplete_grammar.stderr @@ -0,0 +1,17 @@ +error: expected one of "#", "grammar", "pub" at end of input + --> tests/compile-fail/incomplete_grammar.rs:2:1 + | +2 | peg::parser!(); + | ^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `peg::parser` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of "::", "<", "{" at end of input + --> tests/compile-fail/incomplete_grammar.rs:4:1 + | +4 | / peg::parser!( +5 | | grammar parser() for str +6 | | ); + | |_^ + | + = note: this error originates in the macro `peg::parser` (in Nightly builds, run with -Z macro-backtrace for more info)