Add move command for moving (leaf)list instances
Change-Id: I0bff25209f74601a450c12a810200b3c124d65f2
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 253a16a..9f0baf2 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -27,6 +27,7 @@
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<command_class, command_> const command = "command";
x3::rule<createCommandSuggestions_class, x3::unused_type> const createCommandSuggestions = "createCommandSuggestions";
@@ -134,11 +135,105 @@
auto const describe_def =
describe_::name >> space_separator > (dataPathListEnd | anyPath);
+struct mode_table : x3::symbols<MoveMode> {
+ mode_table()
+ {
+ add
+ ("after", MoveMode::After)
+ ("before", MoveMode::Before)
+ ("begin", MoveMode::Begin)
+ ("end", MoveMode::End);
+ }
+} const mode_table;
+
+struct move_absolute_table : x3::symbols<yang::move::Absolute> {
+ move_absolute_table()
+ {
+ add
+ ("begin", yang::move::Absolute::Begin)
+ ("end", yang::move::Absolute::End);
+ }
+} const move_absolute_table;
+
+struct move_relative_table : x3::symbols<yang::move::Relative::Position> {
+ move_relative_table()
+ {
+ add
+ ("before", yang::move::Relative::Position::Before)
+ ("after", yang::move::Relative::Position::After);
+ }
+} const move_relative_table;
+
+struct move_args : x3::parser<move_args> {
+ using attribute_type = move_;
+ template <typename It, typename Ctx, typename RCtx>
+ bool parse(It& begin, It end, Ctx const& ctx, RCtx& rctx, move_& attr) const
+ {
+ ParserContext& parserContext = x3::get<parser_context_tag>(ctx);
+ dataPath_ movePath;
+ auto movePathGrammar = listInstancePath | leafListElementPath;
+ auto res = movePathGrammar.parse(begin, end, ctx, rctx, attr.m_source);
+ if (!res) {
+ parserContext.m_errorMsg = "Expected source path here:";
+ return false;
+ }
+
+ // Try absolute move first.
+ res = (space_separator >> move_absolute_table).parse(begin, end, ctx, rctx, attr.m_destination);
+ if (res) {
+ // Absolute move parsing succeeded, we don't need to parse anything else.
+ return true;
+ }
+
+ // If absolute move didn't succeed, try relative.
+ attr.m_destination = yang::move::Relative{};
+ res = (space_separator >> move_relative_table).parse(begin, end, ctx, rctx, std::get<yang::move::Relative>(attr.m_destination).m_position);
+
+ if (!res) {
+ parserContext.m_errorMsg = "Expected a move position (begin, end, before, after) here:";
+ return false;
+ }
+
+ if (std::holds_alternative<leafListElement_>(attr.m_source.m_nodes.back().m_suffix)) {
+ leaf_data_ value;
+ res = (space_separator >> leaf_data).parse(begin, end, ctx, rctx, value);
+ if (res) {
+ std::get<yang::move::Relative>(attr.m_destination).m_path = {{".", value}};
+ }
+ } else {
+ ListInstance listInstance;
+ // The source list instance will be stored inside the parser context path.
+ // The source list instance will be full data path (with keys included).
+ // However, m_tmpListPath is supposed to store a path with a list without the keys.
+ // So, I pop the last listElement_ (which has the keys) and put in a list_ (which doesn't have the keys).
+ // Example: /mod:cont/protocols[name='ftp'] gets turned into /mod:cont/protocols
+ parserContext.m_tmpListPath = parserContext.currentDataPath();
+ parserContext.m_tmpListPath.m_nodes.pop_back();
+ auto list = list_{std::get<listElement_>(attr.m_source.m_nodes.back().m_suffix).m_name};
+ parserContext.m_tmpListPath.m_nodes.push_back(dataNode_{attr.m_source.m_nodes.back().m_prefix, list});
+
+ res = (space_separator >> listSuffix).parse(begin, end, ctx, rctx, listInstance);
+ if (res) {
+ std::get<yang::move::Relative>(attr.m_destination).m_path = listInstance;
+ }
+ }
+
+ if (!res) {
+ parserContext.m_errorMsg = "Expected a destination here:";
+ }
+
+ return res;
+ }
+} const move_args;
+
+auto const move_def =
+ move_::name >> space_separator >> move_args;
+
auto const createCommandSuggestions_def =
x3::eps;
auto const command_def =
- createCommandSuggestions >> x3::expect[cd | copy | create | delete_rule | set | commit | get | ls | discard | describe | help];
+ createCommandSuggestions >> x3::expect[cd | copy | create | delete_rule | set | commit | get | ls | discard | describe | help | move];
#if __clang__
#pragma GCC diagnostic pop
@@ -155,5 +250,6 @@
BOOST_SPIRIT_DEFINE(describe)
BOOST_SPIRIT_DEFINE(help)
BOOST_SPIRIT_DEFINE(copy)
+BOOST_SPIRIT_DEFINE(move)
BOOST_SPIRIT_DEFINE(command)
BOOST_SPIRIT_DEFINE(createCommandSuggestions)