macros: Add hints for follow-set restrictions

Adds a new call to `rust_inform()` in order to let the user know about
the tokens allowed after the previous match.
Since this changes the error message, tests also need to be adjusted.
This commit is contained in:
Arthur Cohen 2022-03-23 15:10:30 +01:00
parent ff5f3005d0
commit 3e5090608d
7 changed files with 23 additions and 18 deletions

View File

@ -172,6 +172,8 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
}}};
Location error_locus = match.get_match_locus ();
std::string kind_str = "fragment";
auto &allowed_toks = follow_set[last_match.get_frag_spec ().get_kind ()];
// There are two behaviors to handle here: If the follow-up match is a token,
// we want to check if it is allowed.
@ -183,16 +185,12 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
{
case AST::MacroMatch::Tok: {
auto tok = static_cast<AST::Token *> (&match);
auto &allowed_toks
= follow_set[last_match.get_frag_spec ().get_kind ()];
auto is_valid = contains (allowed_toks, tok->get_id ());
if (!is_valid)
// FIXME: Add hint about allowed fragments
rust_error_at (tok->get_match_locus (),
"token %<%s%> is not allowed after %<%s%> fragment",
tok->get_str ().c_str (),
last_match.get_frag_spec ().as_string ().c_str ());
return is_valid;
if (contains (allowed_toks, tok->get_id ()))
return true;
kind_str = "token `"
+ std::string (get_token_description (tok->get_id ())) + "`";
error_locus = tok->get_match_locus ();
break;
}
break;
case AST::MacroMatch::Repetition: {
@ -219,9 +217,16 @@ peculiar_fragment_match_compatible (AST::MacroMatchFragment &last_match,
break;
}
// FIXME: Improve error message
rust_error_at (error_locus, "fragment not allowed after %<%s%> fragment",
rust_error_at (error_locus, "%s is not allowed after %<%s%> fragment",
kind_str.c_str (),
last_match.get_frag_spec ().as_string ().c_str ());
auto allowed_toks_str
= "`" + std::string (get_token_description (allowed_toks[0])) + "`";
for (size_t i = 1; i < allowed_toks.size (); i++)
allowed_toks_str
+= ", `" + std::string (get_token_description (allowed_toks[i])) + "`";
rust_inform (error_locus, "allowed tokens are %s", allowed_toks_str.c_str ());
return false;
}

View File

@ -1,6 +1,6 @@
macro_rules! m {
($a:expr tok) => {
// { dg-error "token .tok. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$a

View File

@ -1,6 +1,6 @@
macro_rules! m {
($a:expr $(tok $es:expr)*) => {
// { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$a

View File

@ -1,6 +1,6 @@
macro_rules! m {
($($es:expr)* tok) => {
// { dg-error "token .tok. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "token .identifier. is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$a

View File

@ -1,6 +1,6 @@
macro_rules! m {
($e:expr $f:expr) => {
// { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$e

View File

@ -1,6 +1,6 @@
macro_rules! m {
($($e:expr)* $($f:expr)*) => {
// { dg-error "fragment not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "fragment is not allowed after .expr. fragment" "" { target *-*-* } .-1 }
// { dg-error "required first macro rule in macro rules definition could not be parsed" "" { target *-*-* } .-2 }
// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
$e

View File

@ -1,5 +1,5 @@
macro_rules! inside_matcher {
(($e:expr tok) tok) => {{}}; // { dg-error "token .tok. is not allowed after .expr. fragment" }
(($e:expr tok) tok) => {{}}; // { dg-error "token .identifier. is not allowed after .expr. fragment" }
// { dg-error "failed to parse macro matcher" "" { target *-*-* } .-1 }
// { dg-error "failed to parse macro match" "" { target *-*-* } .-2 }
// { dg-error "required first macro rule" "" { target *-*-* } .-3 }