macros: Only expand merged repetitions if they contain the same amount
of matches Forbid merging repetitions if the matched fragments do not contain the same amount of repetitions
This commit is contained in:
parent
1bb9a29688
commit
f8c550f7e1
|
@ -30,18 +30,14 @@ SubstituteCtx::substitute_metavar (std::unique_ptr<AST::Token> &metavar)
|
|||
return expanded;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<AST::Token>>
|
||||
SubstituteCtx::substitute_repetition (
|
||||
size_t pattern_start, size_t pattern_end,
|
||||
std::unique_ptr<AST::Token> separator_token)
|
||||
bool
|
||||
SubstituteCtx::check_repetition_amount (size_t pattern_start,
|
||||
size_t pattern_end,
|
||||
size_t &expected_repetition_amount)
|
||||
{
|
||||
rust_assert (pattern_end < macro.size ());
|
||||
bool first_fragment_found = false;
|
||||
bool is_valid = true;
|
||||
|
||||
std::vector<std::unique_ptr<AST::Token>> expanded;
|
||||
|
||||
// Find the first fragment and get the amount of repetitions that we should
|
||||
// perform
|
||||
size_t repeat_amount = 0;
|
||||
for (size_t i = pattern_start; i < pattern_end; i++)
|
||||
{
|
||||
if (macro.at (i)->get_id () == DOLLAR_SIGN)
|
||||
|
@ -59,17 +55,48 @@ SubstituteCtx::substitute_repetition (
|
|||
rust_error_at (frag_token->get_locus (),
|
||||
"metavar %s used in repetition does not exist",
|
||||
frag_token->get_str ().c_str ());
|
||||
// FIXME:
|
||||
return expanded;
|
||||
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
// FIXME: Refactor, ugly
|
||||
repeat_amount = it->second.get_match_amount ();
|
||||
size_t repeat_amount = it->second.get_match_amount ();
|
||||
if (!first_fragment_found)
|
||||
{
|
||||
first_fragment_found = true;
|
||||
expected_repetition_amount = repeat_amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (repeat_amount != expected_repetition_amount)
|
||||
{
|
||||
rust_error_at (
|
||||
frag_token->get_locus (),
|
||||
"different amount of matches used in merged "
|
||||
"repetitions: expected %ld, got %ld",
|
||||
expected_repetition_amount, repeat_amount);
|
||||
is_valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<AST::Token>>
|
||||
SubstituteCtx::substitute_repetition (
|
||||
size_t pattern_start, size_t pattern_end,
|
||||
std::unique_ptr<AST::Token> separator_token)
|
||||
{
|
||||
rust_assert (pattern_end < macro.size ());
|
||||
|
||||
size_t repeat_amount = 0;
|
||||
if (!check_repetition_amount (pattern_start, pattern_end, repeat_amount))
|
||||
return {};
|
||||
|
||||
rust_debug ("repetition amount to use: %lu", repeat_amount);
|
||||
std::vector<std::unique_ptr<AST::Token>> expanded;
|
||||
std::vector<std::unique_ptr<AST::Token>> new_macro;
|
||||
|
||||
// We want to generate a "new macro" to substitute with. This new macro
|
||||
|
|
|
@ -26,6 +26,17 @@ class SubstituteCtx
|
|||
std::vector<std::unique_ptr<AST::Token>> ¯o;
|
||||
std::map<std::string, MatchedFragmentContainer> &fragments;
|
||||
|
||||
/**
|
||||
* Find the repetition amount to use when expanding a repetition, and
|
||||
* check that all fragments used respect that repetition amount
|
||||
*
|
||||
* @param pattern_start Start of the repetition pattern
|
||||
* @param pattern_end End of the repetition pattern
|
||||
* @param repeat_amount Reference to fill with the matched repetition amount
|
||||
*/
|
||||
bool check_repetition_amount (size_t pattern_start, size_t pattern_end,
|
||||
size_t &repeat_amount);
|
||||
|
||||
public:
|
||||
SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input,
|
||||
std::vector<std::unique_ptr<AST::Token>> ¯o,
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
macro_rules! repeat {
|
||||
( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
|
||||
// { dg-error "different amount of matches used in merged repetitions" "" { target *-*-* } .-1 }
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let _ = repeat!(1, 2, 3; 2, 3);
|
||||
|
||||
0
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
macro_rules! repeat {
|
||||
( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let t = repeat!(1, 1; 2, 2);
|
||||
|
||||
t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6
|
||||
}
|
Loading…
Reference in New Issue