//////////////////////////////////////////////////////////////////////////////// // // Copyright 2006 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // https://www.opensource.org/licenses/mit-license.php // //////////////////////////////////////////////////////////////////////////////// #ifndef INCLUDED_CLI2 #define INCLUDED_CLI2 #include #include #include #include #include #include // Represents a single argument. class A2 { public: A2(const std::string&, Lexer::Type); A2(const A2&); A2& operator=(const A2&); bool hasTag(const std::string&) const; void tag(const std::string&); void unTag(const std::string&); void attribute(const std::string&, const std::string&); const std::string attribute(const std::string&) const; const std::string getToken() const; const std::string dump() const; void decompose(); public: Lexer::Type _lextype{Lexer::Type::word}; std::vector _tags{}; std::map _attributes{}; }; // Represents the command line. class CLI2 { public: static int minimumMatchLength; static bool getOverride(int, const char**, File&); static bool getDataLocation(int, const char**, Path&); static void applyOverrides(int, const char**); public: CLI2() = default; void alias(const std::string&, const std::string&); void entity(const std::string&, const std::string&); void add(const std::string&); void add(const std::vector&, int offset = 0); void analyze(); void addFilter(const std::string& arg); void addModifications(const std::string& arg); void addContext(bool readable, bool writeable); void prepareFilter(); const std::vector getWords(); const std::vector getMiscellaneous(); bool canonicalize(std::string&, const std::string&, const std::string&); std::string getBinary() const; std::string getCommand(bool canonical = true) const; const std::string dump(const std::string& title = "CLI2 Parser") const; private: void handleArg0(); void lexArguments(); void demotion(); void aliasExpansion(); void canonicalizeNames(); void categorizeArgs(); void parenthesizeOriginalFilter(); bool findCommand(); bool exactMatch(const std::string&, const std::string&) const; void desugarFilterTags(); void findStrayModifications(); void desugarFilterAttributes(); void desugarFilterPatterns(); void findIDs(); void findUUIDs(); void insertIDExpr(); void lexFilterArgs(); bool isEmptyParenExpression(std::vector::iterator it, bool forward = true) const; void desugarFilterPlainArgs(); void insertJunctions(); void defaultCommand(); std::vector lexExpression(const std::string&); public: std::multimap _entities{}; std::map _aliases{}; std::unordered_map _canonical_cache{}; std::vector _original_args{}; std::vector _args{}; std::vector> _id_ranges{}; std::vector _uuid_list{}; std::string _command{""}; bool _context_added{false}; }; #endif