Rework schemaNode parsing
Change-Id: I7c98b9a2c70370f68ef48b31caf70f6974474364
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 2a1b360..df65519 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -211,16 +211,6 @@
}
};
-struct schemaNode_class {
- template <typename T, typename Iterator, typename Context>
- void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
- {
- auto& parserContext = x3::get<parser_context_tag>(context);
- parserContext.pushPathFragment(ast);
- parserContext.m_curModule = boost::none;
- }
-};
-
struct dataNodeList_class {
template <typename T, typename Iterator, typename Context>
void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
diff --git a/src/path_parser.hpp b/src/path_parser.hpp
index af98208..e2af35e 100644
--- a/src/path_parser.hpp
+++ b/src/path_parser.hpp
@@ -26,7 +26,6 @@
x3::rule<createPathSuggestions_class, x3::unused_type> const createPathSuggestions = "createPathSuggestions";
x3::rule<trailingSlash_class, TrailingSlash> const trailingSlash = "trailingSlash";
x3::rule<dataNode_class, dataNode_> const dataNode = "dataNode";
-x3::rule<schemaNode_class, schemaNode_> const schemaNode = "schemaNode";
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";
@@ -42,6 +41,60 @@
x3::rule<suggestKeysEnd_class, x3::unused_type> const suggestKeysEnd = "suggestKeysEnd";
+struct schemaNode : x3::parser<schemaNode> {
+ using attribute_type = schemaNode_;
+ template <typename It, typename Ctx, typename RCtx, typename Attr>
+ bool parse(It& begin, It end, Ctx const& ctx, RCtx& rctx, Attr& attr) const
+ {
+ x3::symbols<schemaNode_> table(std::string{"schemaNode"}); // The constructor doesn't work with just the string literal
+
+ ParserContext& parserContext = x3::get<parser_context_tag>(ctx);
+ parserContext.m_suggestions.clear();
+ for (const auto& child : parserContext.m_schema.availableNodes(parserContext.currentSchemaPath(), Recursion::NonRecursive)) {
+ schemaNode_ out;
+ std::string parseString;
+ if (child.first) {
+ out.m_prefix = module_{*child.first};
+ parseString = *child.first + ":";
+ }
+ parseString += child.second;
+ switch (parserContext.m_schema.nodeType(parserContext.currentSchemaPath(), child)) {
+ case yang::NodeTypes::Container:
+ case yang::NodeTypes::PresenceContainer:
+ out.m_suffix = container_{child.second};
+ parserContext.m_suggestions.emplace(Completion{parseString + "/"});
+ break;
+ case yang::NodeTypes::Leaf:
+ out.m_suffix = leaf_{child.second};
+ parserContext.m_suggestions.emplace(Completion{parseString + " "});
+ break;
+ case yang::NodeTypes::List:
+ out.m_suffix = list_{child.second};
+ parserContext.m_suggestions.emplace(Completion{parseString, "[", Completion::WhenToAdd::IfFullMatch});
+ break;
+ case yang::NodeTypes::Action:
+ case yang::NodeTypes::AnyXml:
+ case yang::NodeTypes::LeafList:
+ case yang::NodeTypes::Notification:
+ case yang::NodeTypes::Rpc:
+ continue;
+ }
+ table.add(parseString, out);
+ table.add("..", attribute_type{nodeup_{}});
+ if (!child.first) {
+ auto topLevelModule = parserContext.currentSchemaPath().m_nodes.begin()->m_prefix;
+ out.m_prefix = topLevelModule;
+ table.add(topLevelModule->m_name + ":" + parseString, out);
+ }
+ }
+ auto res = table.parse(begin, end, ctx, rctx, attr);
+ if (res) {
+ parserContext.pushPathFragment(attr);
+ }
+ return res;
+ }
+} schemaNode;
+
#if __clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverloaded-shift-op-parentheses"
@@ -101,10 +154,6 @@
auto const createPathSuggestions_def =
x3::eps;
-// leaf cannot be in the middle of a path, however, I need the grammar's attribute to be a vector of variants
-auto const schemaNode_def =
- createPathSuggestions >> -(module) >> (container | list | nodeup | leaf);
-
auto const dataNode_def =
createPathSuggestions >> -(module) >> (container | listElement | nodeup | leaf);
@@ -152,7 +201,6 @@
BOOST_SPIRIT_DEFINE(listElement)
BOOST_SPIRIT_DEFINE(list)
BOOST_SPIRIT_DEFINE(nodeup)
-BOOST_SPIRIT_DEFINE(schemaNode)
BOOST_SPIRIT_DEFINE(dataNode)
BOOST_SPIRIT_DEFINE(container)
BOOST_SPIRIT_DEFINE(leaf)