Rework x3::rule parser

It's possible to define x3::rule's grammar directly. There's no need to
use the BOOST_SPIRIT_DEFINE macro and all the "*_def" stuff. The new
syntax has less boilerplate and is more concise. Some rules had to be
moved around, because now they aren't all defined at the begining of the
file.

There is also one big advantage to this: if you're browsing the parser
code and you're looking at a specifing grammar and want to see the
definition of some other used, you can use your IDE's "Go to
definition". Before you would have to also search the "_def" variable to
actually see the grammar. This is very useful.

Change-Id: I0994603171321a24b9cdf5d67057d5942001a970
diff --git a/src/common_parsers.hpp b/src/common_parsers.hpp
index e7bedd3..285234f 100644
--- a/src/common_parsers.hpp
+++ b/src/common_parsers.hpp
@@ -8,26 +8,21 @@
 #pragma once
 #include <boost/spirit/home/x3.hpp>
 #include "ast_handlers.hpp"
-x3::rule<module_identifier_class, std::string> const module_identifier = "module_identifier";
-x3::rule<module_class, module_> const module = "module";
-x3::rule<node_identifier_class, std::string> const node_identifier = "node_identifier";
-x3::rule<space_separator_class, x3::unused_type> const space_separator = "a space";
-x3::rule<completing_class, x3::unused_type> const completing = "completing";
 
 // This is a pseudo-parser, that fails if we're not completing a command
-auto const completing_def =
+auto const completing = x3::rule<completing_class, x3::unused_type>{"completing"} =
     x3::eps;
 
-auto const node_identifier_def =
+auto const node_identifier = x3::rule<node_identifier_class, std::string>{"node_identifier"} =
     ((x3::alpha | x3::char_("_")) >> *(x3::alnum | x3::char_("_") | x3::char_("-") | x3::char_(".")));
 
-auto const module_def =
+auto const module_identifier = x3::rule<module_identifier_class, std::string>{"module_identifier"} =
+    ((x3::alpha | x3::char_("_")) >> *(x3::alnum | x3::char_("_") | x3::char_("-") | x3::char_(".")));
+
+auto const module = x3::rule<module_class, module_>{"module"} =
     module_identifier >> ':' >> !x3::space;
 
-auto const module_identifier_def =
-    ((x3::alpha | x3::char_("_")) >> *(x3::alnum | x3::char_("_") | x3::char_("-") | x3::char_(".")));
-
-auto const space_separator_def =
+auto const space_separator = x3::rule<space_separator_class, x3::unused_type>{"a space"} =
     x3::omit[+x3::space];
 
 template <typename CoerceTo>
@@ -45,9 +40,3 @@
 // someParser will have its attribute coerced to std::string
 // https://github.com/boostorg/spirit/issues/530#issuecomment-584836532
 template <typename CoerceTo> const as_type<CoerceTo> as{};
-
-BOOST_SPIRIT_DEFINE(node_identifier)
-BOOST_SPIRIT_DEFINE(module)
-BOOST_SPIRIT_DEFINE(module_identifier)
-BOOST_SPIRIT_DEFINE(space_separator)
-BOOST_SPIRIT_DEFINE(completing)
diff --git a/src/grammars.hpp b/src/grammars.hpp
index b1f2878..d0d2d0c 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -67,27 +67,6 @@
 }
 #endif
 
-x3::rule<discard_class, discard_> const discard = "discard";
-x3::rule<ls_class, ls_> const ls = "ls";
-x3::rule<cd_class, cd_> const cd = "cd";
-x3::rule<set_class, set_> const set = "set";
-x3::rule<get_class, get_> const get = "get";
-x3::rule<create_class, create_> const create = "create";
-x3::rule<delete_class, delete_> const delete_rule = "delete_rule";
-x3::rule<commit_class, commit_> const commit = "commit";
-x3::rule<describe_class, describe_> const describe = "describe";
-x3::rule<help_class, help_> const help = "help";
-x3::rule<copy_class, copy_> const copy = "copy";
-x3::rule<move_class, move_> const move = "move";
-x3::rule<dump_class, dump_> const dump = "dump";
-x3::rule<prepare_class, prepare_> const prepare = "prepare";
-x3::rule<exec_class, exec_> const exec = "exec";
-x3::rule<switch_class, switch_> const switch_rule = "switch";
-x3::rule<cancel_class, cancel_> const cancel = "cancel";
-x3::rule<quit_class, quit_> const quit = "quit";
-x3::rule<command_class, command_> const command = "command";
-
-x3::rule<createCommandSuggestions_class, x3::unused_type> const createCommandSuggestions = "createCommandSuggestions";
 
 #if __clang__
 #pragma GCC diagnostic push
@@ -104,30 +83,30 @@
     }
 } const ls_options;
 
-auto const ls_def =
+auto const ls = x3::rule<ls_class, ls_>{"ls"} =
     ls_::name >> *(space_separator >> ls_options) >> -(space_separator > (anyPath | (module >> "*")));
 
-auto const cd_def =
+auto const cd = x3::rule<cd_class, cd_>{"cd"} =
     cd_::name >> space_separator > cdPath;
 
 #if BOOST_VERSION <= 107700
-auto const create_def =
+auto const create = x3::rule<create_class, create_>{"create"} =
     create_::name >> space_separator >
     (x3::eps >> presenceContainerPath |
      x3::eps >> listInstancePath |
      x3::eps >> leafListElementPath);
 
-auto const delete_rule_def =
+auto const delete_rule = x3::rule<delete_class, delete_>{"delete_rule"} =
     delete_::name >> space_separator >
     (x3::eps >> presenceContainerPath |
      x3::eps >> listInstancePath |
      x3::eps >> leafListElementPath |
      x3::eps >> writableLeafPath);
 #else
-auto const create_def =
+auto const create = x3::rule<create_class, create_>{"create"} =
     create_::name >> space_separator > (presenceContainerPath | listInstancePath | leafListElementPath);
 
-auto const delete_rule_def =
+auto const delete_rule = x3::rule<delete_class, delete_>{"delete_rule"} =
     delete_::name >> space_separator > (presenceContainerPath | listInstancePath | leafListElementPath | writableLeafPath);
 #endif
 
@@ -143,18 +122,18 @@
     }
 } const ds_target_table;
 
-auto const get_def =
+auto const get = x3::rule<get_class, get_>{"get"} =
     get_::name
     >> -(space_separator >> "-" > staticSuggestions({"-datastore"}) > "-datastore" > space_separator > dsTargetSuggestions > ds_target_table)
     >> -(space_separator > getPath);
 
-auto const set_def =
+auto const set = x3::rule<set_class, set_>{"set"} =
     set_::name >> space_separator > writableLeafPath > space_separator > leaf_data;
 
-auto const commit_def =
+auto const commit = x3::rule<commit_class, commit_>{"commit"} =
     commit_::name >> x3::attr(commit_());
 
-auto const discard_def =
+auto const discard = x3::rule<discard_class, discard_>{"discard"} =
     discard_::name >> x3::attr(discard_());
 
 struct command_names_table : x3::symbols<decltype(help_::m_cmd)> {
@@ -166,7 +145,10 @@
     }
 } const command_names;
 
-auto const help_def =
+auto const createCommandSuggestions = x3::rule<createCommandSuggestions_class, x3::unused_type>{"createCommandSuggestions"} =
+    x3::eps;
+
+auto const help = x3::rule<help_class, help_>{"help"} =
     help_::name > createCommandSuggestions >> -command_names;
 
 struct datastore_symbol_table : x3::symbols<Datastore> {
@@ -211,10 +193,10 @@
     }
 } const copy_args;
 
-auto const copy_def =
+auto const copy = x3::rule<copy_class, copy_>{"copy"} =
     copy_::name > space_separator > copy_args;
 
-auto const describe_def =
+auto const describe = x3::rule<describe_class, describe_>{"describe"} =
     describe_::name >> space_separator > anyPath;
 
 struct move_mode_table : x3::symbols<MoveMode> {
@@ -312,7 +294,7 @@
     }
 } const move_args;
 
-auto const move_def =
+auto const move = x3::rule<move_class, move_>{"move"} =
     move_::name >> space_separator >> move_args;
 
 struct format_table : x3::symbols<DataFormat> {
@@ -340,28 +322,25 @@
     }
 } const dump_args;
 
-auto const prepare_def =
+auto const prepare = x3::rule<prepare_class, prepare_>{"prepare"} =
     prepare_::name > space_separator > as<dataPath_>[RpcActionPath<AllowInput::Yes>{}];
 
-auto const exec_def =
+auto const exec = x3::rule<exec_class, exec_>{"exec"} =
     exec_::name > -(space_separator > -as<dataPath_>[RpcActionPath<AllowInput::No>{}]);
 
-auto const switch_rule_def =
+auto const switch_rule = x3::rule<switch_class, switch_>{"switch"} =
     switch_::name > space_separator > dsTargetSuggestions > ds_target_table;
 
-auto const cancel_def =
+auto const cancel = x3::rule<cancel_class, cancel_>{"cancel"} =
     cancel_::name >> x3::attr(cancel_{});
 
-auto const dump_def =
+auto const dump = x3::rule<dump_class, dump_>{"dump"} =
     dump_::name > space_separator >> dump_args;
 
-auto const quit_def =
+auto const quit = x3::rule<quit_class, quit_>{"quit"} =
     quit_::name >> x3::attr(quit_{});
 
-auto const createCommandSuggestions_def =
-    x3::eps;
-
-auto const command_def =
+auto const command = x3::rule<command_class, command_>{"command"} =
 #if BOOST_VERSION <= 107800
     x3::eps >>
 #endif
@@ -370,24 +349,3 @@
 #if __clang__
 #pragma GCC diagnostic pop
 #endif
-
-BOOST_SPIRIT_DEFINE(set)
-BOOST_SPIRIT_DEFINE(commit)
-BOOST_SPIRIT_DEFINE(get)
-BOOST_SPIRIT_DEFINE(ls)
-BOOST_SPIRIT_DEFINE(discard)
-BOOST_SPIRIT_DEFINE(cd)
-BOOST_SPIRIT_DEFINE(create)
-BOOST_SPIRIT_DEFINE(delete_rule)
-BOOST_SPIRIT_DEFINE(describe)
-BOOST_SPIRIT_DEFINE(help)
-BOOST_SPIRIT_DEFINE(copy)
-BOOST_SPIRIT_DEFINE(move)
-BOOST_SPIRIT_DEFINE(dump)
-BOOST_SPIRIT_DEFINE(prepare)
-BOOST_SPIRIT_DEFINE(exec)
-BOOST_SPIRIT_DEFINE(switch_rule)
-BOOST_SPIRIT_DEFINE(cancel)
-BOOST_SPIRIT_DEFINE(quit)
-BOOST_SPIRIT_DEFINE(command)
-BOOST_SPIRIT_DEFINE(createCommandSuggestions)
diff --git a/src/leaf_data.hpp b/src/leaf_data.hpp
index e945fda..0e0e499 100644
--- a/src/leaf_data.hpp
+++ b/src/leaf_data.hpp
@@ -17,10 +17,6 @@
 template <typename TYPE>
 struct leaf_data_class;
 
-x3::rule<struct leaf_data_class<yang::IdentityRef>, identityRef_> const leaf_data_identityRef = "leaf_data_identityRef";
-x3::rule<struct leaf_data_class<yang::Binary>, binary_> const leaf_data_binary = "leaf_data_binary";
-x3::rule<struct leaf_data_class<yang::String>, std::string> const leaf_data_string = "leaf_data_string";
-
 using x3::char_;
 
 struct bool_symbol_table : x3::symbols<bool> {
@@ -32,14 +28,14 @@
     }
 } const bool_symbols;
 
-auto const leaf_data_string_def =
+auto const leaf_data_string = x3::rule<struct leaf_data_class<yang::String>, std::string>{"leaf_data_string"} =
     '\'' >> *(char_-'\'') >> '\'' |
     '\"' >> *(char_-'\"') >> '\"';
 
-auto const leaf_data_binary_def =
+auto const leaf_data_binary = x3::rule<struct leaf_data_class<yang::Binary>, binary_>{"leaf_data_binary"} =
     as<std::string>[+(x3::alnum | char_('+') | char_('/')) >> -char_('=') >> -char_('=')];
 
-auto const leaf_data_identityRef_def =
+auto const leaf_data_identityRef = x3::rule<struct leaf_data_class<yang::IdentityRef>, identityRef_>{"leaf_data_identityRef"} =
     -module >> node_identifier;
 
 template <typename It, typename Ctx, typename RCtx, typename Attr>
@@ -210,7 +206,3 @@
 };
 
 auto const leaf_data = LeafData();
-
-BOOST_SPIRIT_DEFINE(leaf_data_string)
-BOOST_SPIRIT_DEFINE(leaf_data_binary)
-BOOST_SPIRIT_DEFINE(leaf_data_identityRef)
diff --git a/src/path_parser.hpp b/src/path_parser.hpp
index b561d01..961db96 100644
--- a/src/path_parser.hpp
+++ b/src/path_parser.hpp
@@ -14,21 +14,6 @@
 
 namespace x3 = boost::spirit::x3;
 
-x3::rule<cdPath_class, dataPath_> const cdPath = "cdPath";
-x3::rule<getPath_class, decltype(get_::m_path)::value_type> const getPath = "getPath";
-x3::rule<presenceContainerPath_class, dataPath_> const presenceContainerPath = "presenceContainerPath";
-x3::rule<listInstancePath_class, dataPath_> const listInstancePath = "listInstancePath";
-x3::rule<leafListElementPath_class, dataPath_> const leafListElementPath = "leafListElementPath";
-x3::rule<initializePath_class, x3::unused_type> const initializePath = "initializePath";
-x3::rule<trailingSlash_class, x3::unused_type> const trailingSlash = "trailingSlash";
-x3::rule<absoluteStart_class, Scope> const absoluteStart = "absoluteStart";
-x3::rule<keyValue_class, keyValue_> const keyValue = "keyValue";
-x3::rule<key_identifier_class, std::string> const key_identifier = "key_identifier";
-x3::rule<listSuffix_class, std::vector<keyValue_>> const listSuffix = "listSuffix";
-x3::rule<createKeySuggestions_class, x3::unused_type> const createKeySuggestions = "createKeySuggestions";
-x3::rule<createValueSuggestions_class, x3::unused_type> const createValueSuggestions = "createValueSuggestions";
-x3::rule<suggestKeysEnd_class, x3::unused_type> const suggestKeysEnd = "suggestKeysEnd";
-x3::rule<class leafListValue_class, leaf_data_> const leafListValue = "leafListValue";
 auto pathEnd = x3::rule<class PathEnd>{"pathEnd"} = &space_separator | x3::eoi;
 
 enum class NodeParserMode {
@@ -65,6 +50,44 @@
     Data
 };
 
+auto const createKeySuggestions = x3::rule<createKeySuggestions_class, x3::unused_type>{"createKeySuggestions"} =
+    x3::eps;
+
+auto const key_identifier = x3::rule<key_identifier_class, std::string>{"key_identifier"} =
+    ((x3::alpha | char_("_")) >> *(x3::alnum | char_("_") | char_("-") | char_(".")));
+
+auto const createValueSuggestions = x3::rule<createValueSuggestions_class, x3::unused_type>{"createValueSuggestions"} =
+    x3::eps;
+
+auto const keyValue = x3::rule<keyValue_class, keyValue_>{"keyValue"} =
+    key_identifier > '=' > createValueSuggestions > leaf_data;
+
+auto const suggestKeysEnd = x3::rule<suggestKeysEnd_class, x3::unused_type>{"suggestKeysEnd"} =
+    x3::eps;
+
+auto const keyValueWrapper =
+    '[' > createKeySuggestions > keyValue > suggestKeysEnd > ']';
+
+// even though we don't allow no keys to be supplied, the star allows me to check which keys are missing
+auto const listSuffix = x3::rule<listSuffix_class, std::vector<keyValue_>>{"listSuffix"} =
+    *keyValueWrapper;
+
+struct SuggestLeafListEnd : x3::parser<SuggestLeafListEnd> {
+    using attribute_type = x3::unused_type;
+    template <typename It, typename Ctx, typename RCtx, typename Attr>
+    bool parse(It& begin, It, Ctx const& ctx, RCtx&, Attr&) const
+    {
+        auto& parserContext = x3::get<parser_context_tag>(ctx);
+        parserContext.m_completionIterator = begin;
+        parserContext.m_suggestions = {Completion{"]"}};
+
+        return true;
+    }
+} const suggestLeafListEnd;
+
+auto const leafListValue = x3::rule<class leafListValue_class, leaf_data_>{"leafListValue"} =
+    '[' >> leaf_data >> suggestLeafListEnd >> ']';
+
 template <NodeParserMode PARSER_MODE, CompletionMode COMPLETION_MODE>
 struct NodeParser : x3::parser<NodeParser<PARSER_MODE, COMPLETION_MODE>> {
     using attribute_type = typename ModeToAttribute<PARSER_MODE>::type;
@@ -262,6 +285,16 @@
     using type = dataPath_;
 };
 
+auto const trailingSlash = x3::rule<trailingSlash_class, x3::unused_type>{"trailingSlash"} =
+    x3::omit['/'];
+
+// A "nothing" parser, which is used to indicate we tried to parse a path
+auto const initializePath = x3::rule<initializePath_class, x3::unused_type>{"initializePath"} =
+    x3::eps;
+
+auto const absoluteStart = x3::rule<absoluteStart_class, Scope>{"absoluteStart"} =
+    x3::omit['/'] >> x3::attr(Scope::Absolute);
+
 template <PathParserMode PARSER_MODE, CompletionMode COMPLETION_MODE>
 struct PathParser : x3::parser<PathParser<PARSER_MODE, COMPLETION_MODE>> {
     using attribute_type = typename ModeToAttribute<PARSER_MODE>::type;
@@ -346,50 +379,6 @@
 #pragma GCC diagnostic ignored "-Woverloaded-shift-op-parentheses"
 #endif
 
-struct SuggestLeafListEnd : x3::parser<SuggestLeafListEnd> {
-    using attribute_type = x3::unused_type;
-    template <typename It, typename Ctx, typename RCtx, typename Attr>
-    bool parse(It& begin, It, Ctx const& ctx, RCtx&, Attr&) const
-    {
-        auto& parserContext = x3::get<parser_context_tag>(ctx);
-        parserContext.m_completionIterator = begin;
-        parserContext.m_suggestions = {Completion{"]"}};
-
-        return true;
-    }
-} const suggestLeafListEnd;
-
-auto const leafListValue_def =
-    '[' >> leaf_data >> suggestLeafListEnd >> ']';
-
-auto const key_identifier_def =
-    ((x3::alpha | char_("_")) >> *(x3::alnum | char_("_") | char_("-") | char_(".")));
-
-auto const createKeySuggestions_def =
-    x3::eps;
-
-auto const createValueSuggestions_def =
-    x3::eps;
-
-auto const suggestKeysEnd_def =
-    x3::eps;
-
-auto const keyValue_def =
-    key_identifier > '=' > createValueSuggestions > leaf_data;
-
-auto const keyValueWrapper =
-    '[' > createKeySuggestions > keyValue > suggestKeysEnd > ']';
-
-// even though we don't allow no keys to be supplied, the star allows me to check which keys are missing
-auto const listSuffix_def =
-    *keyValueWrapper;
-
-auto const absoluteStart_def =
-    x3::omit['/'] >> x3::attr(Scope::Absolute);
-
-auto const trailingSlash_def =
-    x3::omit['/'];
-
 auto const filterConfigFalse = [](const Schema& schema, const std::string& path) {
     return schema.isConfig(path);
 };
@@ -469,46 +458,26 @@
     return nodeType != yang::NodeTypes::Rpc && nodeType != yang::NodeTypes::Action;
 };
 
-auto const getPath_def =
+auto const getPath = x3::rule<getPath_class, decltype(get_::m_path)::value_type>{"getPath"} =
     PathParser<PathParserMode::DataPathListEnd, CompletionMode::Data>{noRpcOrAction} |
     (module >> "*");
 
-auto const cdPath_def =
+auto const cdPath = x3::rule<cdPath_class, dataPath_>{"cdPath"} =
     PathParser<PathParserMode::DataPath, CompletionMode::Data>{[] (const Schema& schema, const std::string& path) {
         return noRpcOrAction(schema, path) && schema.nodeType(path) != yang::NodeTypes::Leaf;
     }};
 
-auto const presenceContainerPath_def =
+auto const presenceContainerPath = x3::rule<presenceContainerPath_class, dataPath_>{"presenceContainerPath"} =
     dataPath;
 
-auto const listInstancePath_def =
+auto const listInstancePath = x3::rule<listInstancePath_class, dataPath_>{"listInstancePath"} =
     dataPath;
 
-auto const leafListElementPath_def =
+auto const leafListElementPath = x3::rule<leafListElementPath_class, dataPath_>{"leafListElementPath"} =
     dataPath;
 
-// A "nothing" parser, which is used to indicate we tried to parse a path
-auto const initializePath_def =
-    x3::eps;
-
 
 
 #if __clang__
 #pragma GCC diagnostic pop
 #endif
-
-BOOST_SPIRIT_DEFINE(keyValue)
-BOOST_SPIRIT_DEFINE(key_identifier)
-BOOST_SPIRIT_DEFINE(listSuffix)
-BOOST_SPIRIT_DEFINE(cdPath)
-BOOST_SPIRIT_DEFINE(getPath)
-BOOST_SPIRIT_DEFINE(presenceContainerPath)
-BOOST_SPIRIT_DEFINE(listInstancePath)
-BOOST_SPIRIT_DEFINE(leafListElementPath)
-BOOST_SPIRIT_DEFINE(initializePath)
-BOOST_SPIRIT_DEFINE(createKeySuggestions)
-BOOST_SPIRIT_DEFINE(createValueSuggestions)
-BOOST_SPIRIT_DEFINE(suggestKeysEnd)
-BOOST_SPIRIT_DEFINE(leafListValue)
-BOOST_SPIRIT_DEFINE(absoluteStart)
-BOOST_SPIRIT_DEFINE(trailingSlash)