From f898953a2ed3bd72374db55cbab6aacb196562ef Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 24 Aug 2014 13:14:52 -0400 Subject: [PATCH] Parser - ::findIdSequence now safely removes nodes out of the iterator loop. --- src/Parser.cpp | 281 ++++++++++++++++++++++++++----------------------- 1 file changed, 147 insertions(+), 134 deletions(-) diff --git a/src/Parser.cpp b/src/Parser.cpp index 75ae49c7b..221ad885e 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -1273,159 +1273,172 @@ void Parser::findAttributeModifier () void Parser::findIdSequence () { context.debug ("Parser::findIdSequence"); - bool action = false; + bool action = true; - std::vector nodes; - collect (nodes); - std::vector ::iterator i; - for (i = nodes.begin (); i != nodes.end (); ++i) + do { - // Container for min/max ID ranges. - std::vector > ranges; + action = false; - // Split the ID list into elements. - std::string raw = (*i)->attribute ("raw"); - std::vector elements; - split (elements, raw, ','); - - bool not_an_id = false; - std::vector ::iterator e; - for (e = elements.begin (); e != elements.end (); ++e) + std::vector nodes; + collect (nodes, collectAll); + std::vector ::iterator i; + for (i = nodes.begin (); i != nodes.end (); ++i) { - // Split the ID range into min/max. - std::vector terms; - split (terms, *e, '-'); + std::string raw = (*i)->attribute ("raw"); - if (terms.size () == 1) + if (raw == "--") + break; + + if (! (*i)->hasTag ("?")) + continue; + + // Container for min/max ID ranges. + std::vector > ranges; + + // Split the ID list into elements. + std::vector elements; + split (elements, raw, ','); + + bool not_an_id = false; + std::vector ::iterator e; + for (e = elements.begin (); e != elements.end (); ++e) { - if (! digitsOnly (terms[0])) + // Split the ID range into min/max. + std::vector terms; + split (terms, *e, '-'); + + if (terms.size () == 1) { - not_an_id = true; - break; + if (! digitsOnly (terms[0])) + { + not_an_id = true; + break; + } + + Nibbler n (terms[0]); + int id; + if (n.getUnsignedInt (id) && + n.depleted ()) + { + ranges.push_back (std::pair (id, id)); + } + else + { + not_an_id = true; + break; + } + } + else if (terms.size () == 2) + { + if (! digitsOnly (terms[0]) || + ! digitsOnly (terms[1])) + { + not_an_id = true; + break; + } + + Nibbler n_min (terms[0]); + Nibbler n_max (terms[1]); + int id_min; + int id_max; + if (n_min.getUnsignedInt (id_min) && + n_min.depleted () && + n_max.getUnsignedInt (id_max) && + n_max.depleted ()) + { + if (id_min > id_max) + throw std::string (STRING_PARSER_RANGE_INVERTED); + + ranges.push_back (std::pair (id_min, id_max)); + } + else + { + not_an_id = true; + break; + } + } + } + + if (not_an_id) + continue; + + // Now convert the ranges into an infix expression. + (*i)->unTag ("?"); + (*i)->removeAllBranches (); + (*i)->tag ("ID"); + + Tree* branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "("); + branch->tag ("OP"); + + std::vector >::iterator r; + for (r = ranges.begin (); r != ranges.end (); ++r) + { + if (r != ranges.begin ()) + { + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "or"); + branch->tag ("OP"); } - Nibbler n (terms[0]); - int id; - if (n.getUnsignedInt (id) && - n.depleted ()) + if (r->first == r->second) { - ranges.push_back (std::pair (id, id)); + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "id"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "=="); + branch->tag ("OP"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", r->first); } else { - not_an_id = true; - break; + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "("); + branch->tag ("OP"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "id"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", ">="); + branch->tag ("OP"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", r->first); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "and"); + branch->tag ("OP"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "id"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", "<="); + branch->tag ("OP"); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", r->second); + + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", ")"); + branch->tag ("OP"); } } - else if (terms.size () == 2) - { - if (! digitsOnly (terms[0]) || - ! digitsOnly (terms[1])) - { - not_an_id = true; - break; - } - Nibbler n_min (terms[0]); - Nibbler n_max (terms[1]); - int id_min; - int id_max; - if (n_min.getUnsignedInt (id_min) && - n_min.depleted () && - n_max.getUnsignedInt (id_max) && - n_max.depleted ()) - { - if (id_min > id_max) - throw std::string (STRING_PARSER_RANGE_INVERTED); - - ranges.push_back (std::pair (id_min, id_max)); - } - else - { - not_an_id = true; - break; - } - } + branch = (*i)->addBranch (new Tree ("argSeq")); + branch->attribute ("raw", ")"); + branch->tag ("OP"); + action = true; + break; } - - if (not_an_id) - continue; - - // Now convert the ranges into an infix expression. - (*i)->unTag ("?"); - (*i)->removeAllBranches (); - (*i)->tag ("ID"); - - Tree* branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "("); - branch->tag ("OP"); - - std::vector >::iterator r; - for (r = ranges.begin (); r != ranges.end (); ++r) - { - if (r != ranges.begin ()) - { - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "or"); - branch->tag ("OP"); - } - - if (r->first == r->second) - { - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "id"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "=="); - branch->tag ("OP"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", r->first); - } - else - { - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "("); - branch->tag ("OP"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "id"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", ">="); - branch->tag ("OP"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", r->first); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "and"); - branch->tag ("OP"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "id"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", "<="); - branch->tag ("OP"); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", r->second); - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", ")"); - branch->tag ("OP"); - } - } - - branch = (*i)->addBranch (new Tree ("argSeq")); - branch->attribute ("raw", ")"); - branch->tag ("OP"); - action = true; } + while (action); - if (action) - context.debug (_tree->dump ()); + context.debug (_tree->dump ()); } ////////////////////////////////////////////////////////////////////////////////