mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Fix bug with invalidated iterators when enforcing precedence in region expressions (#2950)
This commit is contained in:
parent
5222b343a4
commit
8be35cd7b5
2 changed files with 24 additions and 26 deletions
|
|
@ -128,8 +128,7 @@ private:
|
|||
void add_precedence();
|
||||
|
||||
//! Add parenthesis to enforce precedence
|
||||
std::vector<int32_t>::iterator add_parentheses(
|
||||
std::vector<int32_t>::iterator start);
|
||||
gsl::index add_parentheses(gsl::index start);
|
||||
|
||||
//! Remove complement operators from the expression
|
||||
void remove_complement_ops();
|
||||
|
|
|
|||
47
src/cell.cpp
47
src/cell.cpp
|
|
@ -578,17 +578,14 @@ void Region::apply_demorgan(
|
|||
//! precedence than unions using parentheses.
|
||||
//==============================================================================
|
||||
|
||||
std::vector<int32_t>::iterator Region::add_parentheses(
|
||||
std::vector<int32_t>::iterator start)
|
||||
gsl::index Region::add_parentheses(gsl::index start)
|
||||
{
|
||||
int32_t start_token = *start;
|
||||
// Add left parenthesis
|
||||
if (start_token == OP_INTERSECTION) {
|
||||
start = expression_.insert(start - 1, OP_LEFT_PAREN);
|
||||
} else {
|
||||
start = expression_.insert(start + 1, OP_LEFT_PAREN);
|
||||
int32_t start_token = expression_[start];
|
||||
// Add left parenthesis and set new position to be after parenthesis
|
||||
if (start_token == OP_UNION) {
|
||||
start += 2;
|
||||
}
|
||||
start++;
|
||||
expression_.insert(expression_.begin() + start - 1, OP_LEFT_PAREN);
|
||||
|
||||
// Keep track of return iterator distance. If we don't encounter a left
|
||||
// parenthesis, we return an iterator corresponding to wherever the right
|
||||
|
|
@ -600,23 +597,23 @@ std::vector<int32_t>::iterator Region::add_parentheses(
|
|||
|
||||
// Add right parenthesis
|
||||
// While the start iterator is within the bounds of infix
|
||||
while (start < expression_.end()) {
|
||||
while (start + 1 < expression_.size()) {
|
||||
start++;
|
||||
|
||||
// If the current token is an operator and is different than the start token
|
||||
if (*start >= OP_UNION && *start != start_token) {
|
||||
if (expression_[start] >= OP_UNION && expression_[start] != start_token) {
|
||||
// Skip wrapped regions but save iterator position to check precedence and
|
||||
// add right parenthesis, right parenthesis position depends on the
|
||||
// operator, when the operator is a union then do not include the operator
|
||||
// in the region, when the operator is an intersection then include the
|
||||
// operator and next surface
|
||||
if (*start == OP_LEFT_PAREN) {
|
||||
return_it_dist = std::distance(expression_.begin(), start);
|
||||
if (expression_[start] == OP_LEFT_PAREN) {
|
||||
return_it_dist = start;
|
||||
int depth = 1;
|
||||
do {
|
||||
start++;
|
||||
if (*start > OP_COMPLEMENT) {
|
||||
if (*start == OP_RIGHT_PAREN) {
|
||||
if (expression_[start] > OP_COMPLEMENT) {
|
||||
if (expression_[start] == OP_RIGHT_PAREN) {
|
||||
depth--;
|
||||
} else {
|
||||
depth++;
|
||||
|
|
@ -624,10 +621,12 @@ std::vector<int32_t>::iterator Region::add_parentheses(
|
|||
}
|
||||
} while (depth > 0);
|
||||
} else {
|
||||
start = expression_.insert(
|
||||
start_token == OP_UNION ? start - 1 : start, OP_RIGHT_PAREN);
|
||||
if (start_token == OP_UNION) {
|
||||
--start;
|
||||
}
|
||||
expression_.insert(expression_.begin() + start, OP_RIGHT_PAREN);
|
||||
if (return_it_dist > 0) {
|
||||
return expression_.begin() + return_it_dist;
|
||||
return return_it_dist;
|
||||
} else {
|
||||
return start - 1;
|
||||
}
|
||||
|
|
@ -638,7 +637,7 @@ std::vector<int32_t>::iterator Region::add_parentheses(
|
|||
// return iterator
|
||||
expression_.push_back(OP_RIGHT_PAREN);
|
||||
if (return_it_dist > 0) {
|
||||
return expression_.begin() + return_it_dist;
|
||||
return return_it_dist;
|
||||
} else {
|
||||
return start - 1;
|
||||
}
|
||||
|
|
@ -651,21 +650,21 @@ void Region::add_precedence()
|
|||
int32_t current_op = 0;
|
||||
std::size_t current_dist = 0;
|
||||
|
||||
for (auto it = expression_.begin(); it != expression_.end(); it++) {
|
||||
int32_t token = *it;
|
||||
for (gsl::index i = 0; i < expression_.size(); i++) {
|
||||
int32_t token = expression_[i];
|
||||
|
||||
if (token == OP_UNION || token == OP_INTERSECTION) {
|
||||
if (current_op == 0) {
|
||||
// Set the current operator if is hasn't been set
|
||||
current_op = token;
|
||||
current_dist = std::distance(expression_.begin(), it);
|
||||
current_dist = i;
|
||||
} else if (token != current_op) {
|
||||
// If the current operator doesn't match the token, add parenthesis to
|
||||
// assert precedence
|
||||
if (current_op == OP_INTERSECTION) {
|
||||
it = add_parentheses(expression_.begin() + current_dist);
|
||||
i = add_parentheses(current_dist);
|
||||
} else {
|
||||
it = add_parentheses(it);
|
||||
i = add_parentheses(i);
|
||||
}
|
||||
current_op = 0;
|
||||
current_dist = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue