diff --git a/src/CLI2.cpp b/src/CLI2.cpp index 74fbfff8a..8a43c37df 100644 --- a/src/CLI2.cpp +++ b/src/CLI2.cpp @@ -110,6 +110,9 @@ void A2::unTag (const std::string& tag) void A2::attribute (const std::string& name, const std::string& value) { _attributes[name] = value; + + if (name == "raw") + decompose (); } //////////////////////////////////////////////////////////////////////////////// @@ -117,6 +120,9 @@ void A2::attribute (const std::string& name, const std::string& value) void A2::attribute (const std::string& name, const int value) { _attributes[name] = format (value); + + if (name == "raw") + decompose (); } //////////////////////////////////////////////////////////////////////////////// @@ -141,6 +147,64 @@ const std::string A2::getToken () const return i->second; } +//////////////////////////////////////////////////////////////////////////////// +void A2::decompose () +{ + if (_lextype == Lexer::Type::tag) + { + std::string raw = _attributes["raw"]; + attribute ("name", raw.substr (1)); + attribute ("sign", raw.substr (0, 1)); + } + + else if (_lextype == Lexer::Type::substitution) + { + std::string raw = _attributes["raw"]; + + auto slash1 = raw.find ("/"); + auto slash2 = raw.find ("/", slash1 + 1); + auto slash3 = raw.find ("/", slash2 + 1); + + attribute ("from", raw.substr (slash1 + 1, slash2 - slash1 - 1)); + attribute ("to", raw.substr (slash2 + 1, slash3 - slash2 - 1)); + attribute ("global", raw.substr (slash3 + 1) == "g" ? 1 : 0); + } + + else if (_lextype == Lexer::Type::pair) + { + std::string raw = _attributes["raw"]; + + // TODO name:value --> canonical="name" value="value" + // TODO name=value --> canonical="name" value="value" + // TODO name:=value --> canonical="name" value="value" + // TODO name::value --> canonical="name" value="value" + // TODO name.mod:value --> + // TODO name.mod=value --> + // TODO name.mod:=value --> + // TODO name.mod::value --> + auto colon = raw.find (':'); + auto equal = raw.find ('='); + + // Q: Which of ':', '=' is the separator? + // A: Whichever comes first. For example: + // name:a=b + // name=a:b + // Both are valid, and 'name' is the attribute name in each case. + std::string::size_type separator = std::min (colon, equal); + std::string name = raw.substr (0, separator); + std::string value = raw.substr (separator + 1); + + attribute ("name", name); + attribute ("value", value); + + if (raw.substr (0, 3) == "rc:") + tag ("RC"); + + if (raw.substr (0, 3) == "rc.") + tag ("CONFIG"); + } +} + //////////////////////////////////////////////////////////////////////////////// const std::string A2::dump () const { @@ -433,7 +497,6 @@ void CLI2::analyze () // Process _args. aliasExpansion (); - findOverrides (); if (! findCommand ()) { defaultCommand (); @@ -441,6 +504,8 @@ void CLI2::analyze () throw std::string (STRING_TRIVIAL_INPUT); } + canonicalizeNames (); + if (context.config.getInteger ("debug.parser") >= 3) context.debug (dump ("CLI2::analyze end")); } @@ -573,9 +638,9 @@ void CLI2::prepareFilter (bool applyContext) insertJunctions (); // Deliberately after all desugar calls. // Decompose the elements for MODIFICATIONs. - decomposeModAttributes (); - decomposeModTags (); - decomposeModSubstitutions (); + //decomposeModAttributes (); + //decomposeModTags (); + //decomposeModSubstitutions (); } //////////////////////////////////////////////////////////////////////////////// @@ -811,34 +876,21 @@ void CLI2::aliasExpansion () } //////////////////////////////////////////////////////////////////////////////// -// Scan all arguments that begin with either "rc:" or "rc.", extract the -// name/values. -void CLI2::findOverrides () +// Scan all arguments and canonicalize names that need it. +void CLI2::canonicalizeNames () { bool changes = false; - std::string raw; - for (auto& a : _args) { - raw = a.attribute ("raw"); - if (raw.length () > 3 && - raw.find ("rc:") == 0) + if (a._lextype == Lexer::Type::pair) { - a.tag ("RC"); - a.attribute ("file", raw.substr (3)); - changes = true; - } - else if (raw.length () > 3 && - raw.find ("rc.") == 0) - { - auto sep = raw.find ('=', 3); - if (sep == std::string::npos) - sep = raw.find (':', 3); - if (sep != std::string::npos) + std::string name = a.attribute ("name"); + std::string canonical; + if (canonicalize (canonical, "pseudo", name) || + canonicalize (canonical, "attribute", name) || + canonicalize (canonical, "uda", name)) { - a.tag ("CONFIG"); - a.attribute ("name", raw.substr (3, sep - 3)); - a.attribute ("value", raw.substr (sep + 1)); + a.attribute ("canonical", canonical); changes = true; } } @@ -846,7 +898,7 @@ void CLI2::findOverrides () if (changes && context.config.getInteger ("debug.parser") >= 3) - context.debug (dump ("CLI2::analyze findOverrides")); + context.debug (dump ("CLI2::analyze canonicalizeNames")); } //////////////////////////////////////////////////////////////////////////////// @@ -1459,8 +1511,7 @@ void CLI2::insertIDExpr () } //////////////////////////////////////////////////////////////////////////////// -// TODO Removed because this algorithm is unreliable. - +// TODO Removed because this algorithm is unreliable. Fix it. void CLI2::desugarFilterPlainArgs () { /* diff --git a/src/CLI2.h b/src/CLI2.h index fd887ee18..6725dfb54 100644 --- a/src/CLI2.h +++ b/src/CLI2.h @@ -49,6 +49,9 @@ public: const std::string getToken () const; const std::string dump () const; +private: + void decompose (); + public: Lexer::Type _lextype; std::vector _tags; @@ -88,7 +91,7 @@ private: void lexArguments (); void demoteDOM (); void aliasExpansion (); - void findOverrides (); + void canonicalizeNames (); bool findCommand (); bool exactMatch (const std::string&, const std::string&) const; void desugarFilterTags ();