blob: f26b1649287e87e356c1d675d3e72c4c5af5bf80 [file] [log] [blame]
Václav Kubernátd6662962018-03-22 17:41:33 +01001/*
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*/
Václav Kubernátf2e463f2018-05-28 15:51:08 +02008#include <experimental/iterator>
Václav Kubernát2315c732018-05-16 20:25:55 +02009#include <ostream>
Václav Kubernát48fc3832018-05-28 14:21:22 +020010#include "parser.hpp"
Václav Kubernát624a8872018-03-02 17:28:47 +010011
12TooManyArgumentsException::~TooManyArgumentsException() = default;
13
Václav Kubernátb96eef72018-05-04 19:10:22 +020014InvalidCommandException::~InvalidCommandException() = default;
15
Václav Kubernát2a9e1792018-05-28 12:53:48 +020016
Václav Kubernát48fc3832018-05-28 14:21:22 +020017Parser::Parser(const Schema& schema)
18 : m_schema(schema)
Václav Kubernát624a8872018-03-02 17:28:47 +010019{
20}
21
Václav Kubernátf2e463f2018-05-28 15:51:08 +020022struct nodeToDataString : public boost::static_visitor<std::string> {
23 std::string operator()(const listElement_& node) const
24 {
25 std::ostringstream res;
26 res << node.m_name + "[";
27 std::transform(node.m_keys.begin(), node.m_keys.end(),
28 std::experimental::make_ostream_joiner(res, ' '),
29 [] (const auto& it) { return it.first + "=" + it.second; });
30 res << "]";
31 return res.str();
32 }
33 std::string operator()(const nodeup_&) const
34 {
35 return "..";
36 }
37 template <class T>
38 std::string operator()(const T& node) const
39 {
40 return node.m_name;
41 }
42};
43
Václav Kubernátb61336d2018-05-28 17:35:03 +020044command_ Parser::parseCommand(const std::string& line, std::ostream& errorStream)
Václav Kubernát624a8872018-03-02 17:28:47 +010045{
Václav Kubernátb61336d2018-05-28 17:35:03 +020046 command_ parsedCommand;
Václav Kubernát48fc3832018-05-28 14:21:22 +020047 ParserContext ctx(m_schema, m_curDir);
Václav Kubernát624a8872018-03-02 17:28:47 +010048 auto it = line.begin();
Václav Kubernátd6662962018-03-22 17:41:33 +010049
Václav Kubernát2315c732018-05-16 20:25:55 +020050 boost::spirit::x3::error_handler<std::string::const_iterator> errorHandler(it, line.end(), errorStream);
51
Václav Kubernátb96eef72018-05-04 19:10:22 +020052 auto grammar =
53 x3::with<parser_context_tag>(ctx)[
Václav Kubernátb61336d2018-05-28 17:35:03 +020054 x3::with<x3::error_handler_tag>(std::ref(errorHandler))[command]
Václav Kubernátb96eef72018-05-04 19:10:22 +020055 ];
56 bool result = x3::phrase_parse(it, line.end(), grammar, space, parsedCommand);
Václav Kubernátd6662962018-03-22 17:41:33 +010057
Václav Kubernátb96eef72018-05-04 19:10:22 +020058 if (!result || it != line.end()) {
59 throw InvalidCommandException(std::string(it, line.end()) + " this was left of input");
Václav Kubernát624a8872018-03-02 17:28:47 +010060 }
61
Václav Kubernátd6662962018-03-22 17:41:33 +010062 return parsedCommand;
Václav Kubernát624a8872018-03-02 17:28:47 +010063}
Václav Kubernát2a9e1792018-05-28 12:53:48 +020064
Václav Kubernát48fc3832018-05-28 14:21:22 +020065void Parser::changeNode(const path_& name)
Václav Kubernát2a9e1792018-05-28 12:53:48 +020066{
Václav Kubernát2a9e1792018-05-28 12:53:48 +020067 for (const auto& it : name.m_nodes) {
Václav Kubernát814fa412018-05-25 19:47:18 +020068 if (it.type() == typeid(nodeup_))
69 m_curDir.m_nodes.pop_back();
70 else
71 m_curDir.m_nodes.push_back(it);
Václav Kubernát2a9e1792018-05-28 12:53:48 +020072 }
73}
Václav Kubernát814fa412018-05-25 19:47:18 +020074
Václav Kubernát48fc3832018-05-28 14:21:22 +020075std::string Parser::currentNode() const
Václav Kubernát2a9e1792018-05-28 12:53:48 +020076{
Václav Kubernát814fa412018-05-25 19:47:18 +020077 std::string res;
78 for (const auto& it : m_curDir.m_nodes) {
Václav Kubernátf2e463f2018-05-28 15:51:08 +020079 res = joinPaths(res, boost::apply_visitor(nodeToDataString(), it));
Václav Kubernát814fa412018-05-25 19:47:18 +020080 }
81
82 return res;
Václav Kubernát2a9e1792018-05-28 12:53:48 +020083}