blob: ae7a98067e745a03bcb8c4e0b81c3333c6229e51 [file] [log] [blame]
Václav Kubernát0a2a2e82018-05-11 13:59:12 +02001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
3 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
4 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8
9#pragma once
10
Václav Kubernát509ce652019-05-29 19:46:44 +020011#include <boost/spirit/home/x3.hpp>
Václav Kubernát24df80e2018-06-06 15:18:03 +020012#include "ast_commands.hpp"
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020013#include "ast_handlers.hpp"
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010014#include "common_parsers.hpp"
15#include "leaf_data.hpp"
Václav Kubernátd0ea9b22020-04-24 00:44:15 +020016#include "path_parser.hpp"
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020017
Václav Kubernát60d6f292018-05-25 09:45:32 +020018
Václav Kubernát6d791432018-10-25 16:00:35 +020019x3::rule<discard_class, discard_> const discard = "discard";
Václav Kubernát11afac72018-07-18 14:59:53 +020020x3::rule<ls_class, ls_> const ls = "ls";
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020021x3::rule<cd_class, cd_> const cd = "cd";
Václav Kubernát07204242018-06-04 18:12:09 +020022x3::rule<set_class, set_> const set = "set";
Václav Kubernátb6ff0b62018-08-30 16:14:53 +020023x3::rule<get_class, get_> const get = "get";
Václav Kubernátb61336d2018-05-28 17:35:03 +020024x3::rule<create_class, create_> const create = "create";
25x3::rule<delete_class, delete_> const delete_rule = "delete_rule";
Václav Kubernát812ee282018-08-30 17:10:03 +020026x3::rule<commit_class, commit_> const commit = "commit";
Václav Kubernát9cfcd872020-02-18 12:34:02 +010027x3::rule<describe_class, describe_> const describe = "describe";
Václav Kubernát054cc992019-02-21 14:23:52 +010028x3::rule<help_class, help_> const help = "help";
Václav Kubernát7160a132020-04-03 02:11:01 +020029x3::rule<copy_class, copy_> const copy = "copy";
Václav Kubernátb61336d2018-05-28 17:35:03 +020030x3::rule<command_class, command_> const command = "command";
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020031
Václav Kubernát57272422019-02-08 12:48:24 +010032x3::rule<createCommandSuggestions_class, x3::unused_type> const createCommandSuggestions = "createCommandSuggestions";
Václav Kubernát5c75b252018-10-10 18:33:47 +020033
Václav Kubernát41378452018-06-06 16:29:40 +020034#if __clang__
35#pragma GCC diagnostic push
36#pragma GCC diagnostic ignored "-Woverloaded-shift-op-parentheses"
37#endif
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020038
Václav Kubernát509ce652019-05-29 19:46:44 +020039namespace ascii = boost::spirit::x3::ascii;
40
Václav Kubernáte7d4aea2018-09-11 18:15:48 +020041struct ls_options_table : x3::symbols<LsOption> {
42 ls_options_table()
43 {
Václav Kubernátbf083ec2019-02-19 13:58:09 +010044 add
45 ("--recursive", LsOption::Recursive);
Václav Kubernáte7d4aea2018-09-11 18:15:48 +020046 }
47} const ls_options;
48
Václav Kubernát11afac72018-07-18 14:59:53 +020049auto const ls_def =
Václav Kubernátbeaa8aa2020-04-29 22:39:34 +020050 ls_::name >> *(space_separator >> ls_options) >> -(space_separator >> (dataPathListEnd | dataPath | schemaPath | (module >> "*")));
Václav Kubernát11afac72018-07-18 14:59:53 +020051
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020052auto const cd_def =
Václav Kubernátbf083ec2019-02-19 13:58:09 +010053 cd_::name >> space_separator > dataPath;
Václav Kubernát0a2a2e82018-05-11 13:59:12 +020054
Václav Kubernátb61336d2018-05-28 17:35:03 +020055auto const create_def =
Václav Kubernátf5f64f02019-03-19 17:15:47 +010056 create_::name >> space_separator > (presenceContainerPath | listInstancePath);
Václav Kubernátb61336d2018-05-28 17:35:03 +020057
58auto const delete_rule_def =
Václav Kubernátf5f64f02019-03-19 17:15:47 +010059 delete_::name >> space_separator > (presenceContainerPath | listInstancePath);
Václav Kubernát07204242018-06-04 18:12:09 +020060
Václav Kubernátb6ff0b62018-08-30 16:14:53 +020061auto const get_def =
Václav Kubernát9456b5c2019-10-02 21:14:52 +020062 get_::name >> -(space_separator >> ((dataPathListEnd | dataPath) | (module >> "*")));
Václav Kubernátb6ff0b62018-08-30 16:14:53 +020063
Václav Kubernát07204242018-06-04 18:12:09 +020064auto const set_def =
Václav Kubernát989b5de2019-02-20 16:28:35 +010065 set_::name >> space_separator > leafPath > space_separator > leaf_data;
Václav Kubernátb61336d2018-05-28 17:35:03 +020066
Václav Kubernát812ee282018-08-30 17:10:03 +020067auto const commit_def =
Václav Kubernátbf083ec2019-02-19 13:58:09 +010068 commit_::name >> x3::attr(commit_());
Václav Kubernát812ee282018-08-30 17:10:03 +020069
Václav Kubernát6d791432018-10-25 16:00:35 +020070auto const discard_def =
Václav Kubernátbf083ec2019-02-19 13:58:09 +010071 discard_::name >> x3::attr(discard_());
Václav Kubernát6d791432018-10-25 16:00:35 +020072
Václav Kubernát054cc992019-02-21 14:23:52 +010073struct command_names_table : x3::symbols<decltype(help_::m_cmd)> {
74 command_names_table()
75 {
76 boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([this](auto cmd) {
77 add(commandNamesVisitor()(cmd), decltype(help_::m_cmd)(cmd));
78 });
79 }
80} const command_names;
81
82auto const help_def =
83 help_::name > createCommandSuggestions >> -command_names;
84
Václav Kubernát7160a132020-04-03 02:11:01 +020085struct datastore_symbol_table : x3::symbols<Datastore> {
86 datastore_symbol_table()
87 {
88 add
89 ("running", Datastore::Running)
90 ("startup", Datastore::Startup);
91 }
92} const datastore;
93
94auto copy_source = x3::rule<class source, Datastore>{"source datastore"} = datastore;
95auto copy_destination = x3::rule<class source, Datastore>{"destination datastore"} = datastore;
96
97const auto datastoreSuggestions = x3::eps[([](auto& ctx) {
98 auto& parserContext = x3::get<parser_context_tag>(ctx);
99 parserContext.m_suggestions = {Completion{"running", " "}, Completion{"startup", " "}};
100 parserContext.m_completionIterator = _where(ctx).begin();
101})];
102
103struct copy_args : x3::parser<copy_args> {
104 using attribute_type = copy_;
105 template <typename It, typename Ctx, typename RCtx>
106 bool parse(It& begin, It end, Ctx const& ctx, RCtx& rctx, copy_& attr) const
107 {
108 auto& parserContext = x3::get<parser_context_tag>(ctx);
109 auto iterBeforeDestination = begin;
110 auto save_iter = x3::no_skip[x3::eps[([&iterBeforeDestination](auto& ctx) {iterBeforeDestination = _where(ctx).begin();})]];
111 auto grammar = datastoreSuggestions > copy_source > space_separator > datastoreSuggestions > save_iter > copy_destination;
112
113 try {
114 grammar.parse(begin, end, ctx, rctx, attr);
115 } catch (x3::expectation_failure<It>& ex) {
116 using namespace std::string_literals;
117 parserContext.m_errorMsg = "Expected "s + ex.which() + " here:";
118 throw;
119 }
120
121 if (attr.m_source == attr.m_destination) {
122 begin = iterBeforeDestination; // Restoring the iterator here makes the error caret point to the second datastore
123 parserContext.m_errorMsg = "Source datastore and destination datastore can't be the same.";
124 return false;
125 }
126
127 return true;
128 }
129} copy_args;
130
131auto const copy_def =
132 copy_::name > space_separator > copy_args;
133
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100134auto const describe_def =
135 describe_::name >> space_separator > (dataPathListEnd | dataPath | schemaPath);
136
Václav Kubernát57272422019-02-08 12:48:24 +0100137auto const createCommandSuggestions_def =
Václav Kubernátbf083ec2019-02-19 13:58:09 +0100138 x3::eps;
Václav Kubernát57272422019-02-08 12:48:24 +0100139
Václav Kubernátb61336d2018-05-28 17:35:03 +0200140auto const command_def =
Václav Kubernát7160a132020-04-03 02:11:01 +0200141 createCommandSuggestions >> x3::expect[cd | copy | create | delete_rule | set | commit | get | ls | discard | describe | help];
Václav Kubernát41378452018-06-06 16:29:40 +0200142
143#if __clang__
144#pragma GCC diagnostic pop
145#endif
Václav Kubernátb61336d2018-05-28 17:35:03 +0200146
Václav Kubernát07204242018-06-04 18:12:09 +0200147BOOST_SPIRIT_DEFINE(set)
Václav Kubernát812ee282018-08-30 17:10:03 +0200148BOOST_SPIRIT_DEFINE(commit)
Václav Kubernátb6ff0b62018-08-30 16:14:53 +0200149BOOST_SPIRIT_DEFINE(get)
Václav Kubernát11afac72018-07-18 14:59:53 +0200150BOOST_SPIRIT_DEFINE(ls)
Václav Kubernát6d791432018-10-25 16:00:35 +0200151BOOST_SPIRIT_DEFINE(discard)
Václav Kubernát0a2a2e82018-05-11 13:59:12 +0200152BOOST_SPIRIT_DEFINE(cd)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200153BOOST_SPIRIT_DEFINE(create)
154BOOST_SPIRIT_DEFINE(delete_rule)
Václav Kubernát9cfcd872020-02-18 12:34:02 +0100155BOOST_SPIRIT_DEFINE(describe)
Václav Kubernát054cc992019-02-21 14:23:52 +0100156BOOST_SPIRIT_DEFINE(help)
Václav Kubernát7160a132020-04-03 02:11:01 +0200157BOOST_SPIRIT_DEFINE(copy)
Václav Kubernátb61336d2018-05-28 17:35:03 +0200158BOOST_SPIRIT_DEFINE(command)
Václav Kubernát57272422019-02-08 12:48:24 +0100159BOOST_SPIRIT_DEFINE(createCommandSuggestions)