Fix parsing issue with get
The bug was actually a little bit more complex, because not only the
completion was wrong, the actual parsing was wrong too. If the input
path was "ietf-netconf-monitoring:netconf-state/s", then nothing would
get successfully parsed, even though the first fragment was valid. This
is the reason why the completion was wrong: the CLI thought "okay I
didn't parse anything, so I'm going to give suggestions for top-level
nodes". That's why after completing "ietf-netconf-monitoring:netconf/s",
top-level nodes were suggested (because the parser esentially "get s"
begin completed).
As to why the bug actually happened was this: first, the getPath rule
would try a path with a key-less list at the end. That one failed,
because there's no list at the end, that's pretty simple. Then the
second alternative is tried. However, for some reason, Spirit doesn't
reset the input iterator after the first alternative fails. This is
because this "input iterator reset" isn't done automatically, but it is
usually done by the x3::rule class. If I wanted this functionality, I
would have to wrap my PathParser with this class. So, the second
alternative only has "s" (the last character in the input) to work with.
So, how I fixed this: first of all, I made the DataPathListEnd mode of
the parser not requiring to actually have the key-less list at the end.
That means there don't have to be two alternatives in `getPath`. This is
good, because less alternatives is always easier to work in Spirit (from
experience, especially when working with rules that have a vector
attribute).
Issue: https://tree.taiga.io/project/jktjkt-netconf-cli/issue/194
Change-Id: Id3a07d2acd20b1e8fa8c8946a55793d8995e5a62
diff --git a/src/path_parser.hpp b/src/path_parser.hpp
index 04a2dba..6725831 100644
--- a/src/path_parser.hpp
+++ b/src/path_parser.hpp
@@ -291,8 +291,8 @@
if constexpr (PARSER_MODE == PathParserMode::DataPathListEnd || PARSER_MODE == PathParserMode::AnyPath) {
if (!res || !pathEnd.parse(begin, end, ctx, rctx, x3::unused)) {
dataNode_ attrNodeList;
- res = incompleteDataNode<COMPLETION_MODE>{m_filterFunction}.parse(begin, end, ctx, rctx, attrNodeList);
- if (res) {
+ auto hasListEnd = incompleteDataNode<COMPLETION_MODE>{m_filterFunction}.parse(begin, end, ctx, rctx, attrNodeList);
+ if (hasListEnd) {
attrData.m_nodes.emplace_back(attrNodeList);
// If the trailing slash matches, no more nodes are parsed.
// That means no more completion. So, I generate them
@@ -460,7 +460,6 @@
auto const getPath_def =
PathParser<PathParserMode::DataPathListEnd, CompletionMode::Data>{noRpcOrAction} |
- PathParser<PathParserMode::DataPath, CompletionMode::Data>{noRpcOrAction} |
(module >> "*");
auto const cdPath_def =