From ed085bd09e66741f58f8d85b3845d24672787609 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 1 Sep 2013 11:54:41 -0400 Subject: [PATCH] A3t::findIdSequence - Added support for ID ranges and lists. Creates a min/max range instead of enumerating all IDs, which is an improvement. - Extended test script. --- src/parser/A3t.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++ src/parser/A3t.h | 1 + src/parser/run | 2 +- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/parser/A3t.cpp b/src/parser/A3t.cpp index 4bf5112fd..33f454bbe 100644 --- a/src/parser/A3t.cpp +++ b/src/parser/A3t.cpp @@ -31,6 +31,7 @@ #include #include #include +#include static const int minimumMatchLength = 3; @@ -68,6 +69,7 @@ Tree* A3t::parse () findTag (); findAttribute (); findAttributeModifier (); + findIdSequence (); validate (); @@ -475,6 +477,91 @@ void A3t::findAttributeModifier () } } +//////////////////////////////////////////////////////////////////////////////// +// A sequence can be: +// +// a single ID: 1 +// a list of IDs: 1,3,5 +// a list of IDs: 1 3 5 +// a range: 5-10 +// or a combination: 1,3,5-10 12 +// +// If a sequence is followed by a non-number, then subsequent numbers are not +// interpreted as IDs. For example: +// +// 1 2 three 4 +// +// The sequence is "1 2". +// +void A3t::findIdSequence () +{ + std::vector ::iterator i; + for (i = _tree->_branches.begin (); i != _tree->_branches.end (); ++i) + { + // Parser override operator. + if ((*i)->attribute ("raw") == "--") + break; + + // Skip known args. + if (! (*i)->hasTag ("?")) + continue; + + std::string raw = (*i)->attribute ("raw"); + Nibbler n (raw); + + std::vector > ranges; + int id; + if (n.getUnsignedInt (id)) + { + if (n.skip ('-')) + { + int end; + if (!n.getUnsignedInt (end)) + throw std::string (STRING_A3_ID_AFTER_HYPHEN); + + if (id > end) + throw std::string (STRING_A3_RANGE_INVERTED); + + ranges.push_back (std::pair (id, end)); + } + else + ranges.push_back (std::pair (id, id)); + + while (n.skip (',')) + { + if (n.getUnsignedInt (id)) + { + if (n.skip ('-')) + { + int end; + if (!n.getUnsignedInt (end)) + throw std::string (STRING_A3_ID_AFTER_HYPHEN); + + if (id > end) + throw std::string (STRING_A3_RANGE_INVERTED); + + ranges.push_back (std::pair (id, end)); + } + else + ranges.push_back (std::pair (id, id)); + } + else + throw std::string (STRING_A3_MALFORMED_ID); + } + + (*i)->unTag ("?"); + (*i)->tag ("ID"); + std::vector >::iterator r; + for (r = ranges.begin (); r != ranges.end (); ++r) + { + Tree* branch = (*i)->addBranch (new Tree ("range")); + branch->attribute ("min", r->first); + branch->attribute ("max", r->second); + } + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Validate the parse tree. void A3t::validate () @@ -483,6 +570,8 @@ void A3t::validate () std::vector ::iterator i; for (i = _tree->_branches.begin (); i != _tree->_branches.end (); ++i) if ((*i)->hasTag ("?")) + // TODO Restore the exception, when functionality is high enough to + // tolerate it. //throw std::string ("Unrecognized argument '") + (*i)->attribute ("raw") + "'"; std::cout << "Unrecognized argument '" << (*i)->attribute ("raw") << "'\n"; diff --git a/src/parser/A3t.h b/src/parser/A3t.h index b92e10b9b..6b85ab85b 100644 --- a/src/parser/A3t.h +++ b/src/parser/A3t.h @@ -51,6 +51,7 @@ private: void findTag (); void findAttribute (); void findAttributeModifier (); + void findIdSequence (); void validate (); private: diff --git a/src/parser/run b/src/parser/run index ff9305478..56f594558 100755 --- a/src/parser/run +++ b/src/parser/run @@ -8,7 +8,7 @@ #echo; ./args rc:x rc.debug:1 1234 done pri:H #echo; ./args rc:x rc.debug:1 a.b\