add class representing the node tree

add CParser class

This class holds the definitions of all the grammars. It also holds a reference a CTree instance it uses when parsing. This means, that it doesn't have to be declared globally.

Change-Id: I3ca23253b546e26612106067045e1e7d3e2ef919
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7d0c949..8cd1aa9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,8 @@
 
 set(netconf-cli_SRCS
     src/main.cpp
+    src/CTree.cpp
+    src/CParser.cpp
     )
 
 add_executable(netconf-cli ${netconf-cli_SRCS})
diff --git a/src/CParser.cpp b/src/CParser.cpp
new file mode 100644
index 0000000..75af7c0
--- /dev/null
+++ b/src/CParser.cpp
@@ -0,0 +1,23 @@
+#include "CParser.hpp"
+
+TooManyArgumentsException::~TooManyArgumentsException() = default;
+
+CParser::CParser(const CTree& tree)
+    : m_tree(tree)
+{
+}
+
+
+Cmd CParser::parseInput(const std::string& line)
+{
+    Cmd args;
+    auto it = line.begin();
+    //bool result = x3::phrase_parse(it, line.end(), command, space, args);
+    //std::cout << "success: " << result << std::endl;
+    if (it != line.end()) {
+        throw TooManyArgumentsException(std::string(it, line.end()));
+    }
+
+
+    return args;
+}
diff --git a/src/CParser.hpp b/src/CParser.hpp
new file mode 100644
index 0000000..c3333af
--- /dev/null
+++ b/src/CParser.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+ */
+
+#pragma once
+#include <boost/spirit/home/x3.hpp>
+#include "CTree.hpp"
+namespace x3 = boost::spirit::x3;
+namespace ascii = boost::spirit::x3::ascii;
+using Cmd = std::vector<std::string>;
+using x3::alpha;
+using x3::lit;
+using x3::char_;
+using x3::_attr;
+using x3::lexeme;
+using ascii::space;
+
+class TooManyArgumentsException : public std::invalid_argument {
+public:
+    using std::invalid_argument::invalid_argument;
+    ~TooManyArgumentsException() override;
+};
+
+class CParser {
+public:
+    CParser(const CTree& tree);
+    Cmd parseInput(const std::string& line);
+
+private:
+    const CTree& m_tree;
+};
diff --git a/src/CTree.cpp b/src/CTree.cpp
new file mode 100644
index 0000000..994515a
--- /dev/null
+++ b/src/CTree.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#include "CTree.hpp"
+
+InvalidNodeException::~InvalidNodeException() = default;
+
+std::string joinPaths(const std::string& prefix, const std::string& suffix)
+{
+    if (prefix.empty() || suffix.empty())
+        return prefix + suffix;
+    else
+        return prefix + '/' + suffix;
+}
+
+const std::unordered_set<std::string>& CTree::children(const std::string& node) const
+{
+    return m_nodes.at(node);
+}
+
+bool CTree::checkNode(const std::string& location, const std::string& node) const
+{
+    if (node == ".." || node.empty())
+        return true;
+    const auto& childrenRef = children(location); //first, get a reference to all children
+    if (childrenRef.find(node) == childrenRef.end()) { //find the desired node, if it isn't present throw an exception
+        throw InvalidNodeException(node);
+    }
+    return true;
+}
+void CTree::changeNode(const std::string& node)
+{
+    if (node.empty()) {
+        m_curDir = "";
+        return;
+    }
+    m_curDir += joinPaths(m_curDir, node);
+}
+std::string CTree::currentNode() const
+{
+    return m_curDir;
+}
+
+void CTree::addNode(const std::string& location, const std::string& name)
+{
+    m_nodes.at(location).insert(name);
+
+    //create a new set of children for the new node
+    m_nodes.emplace(joinPaths(location, name), std::unordered_set<std::string>());
+}
+void CTree::initDefault()
+{
+    m_nodes.emplace("", std::unordered_set<std::string>());
+    addNode("", "aaa");
+    addNode("", "bbb");
+    addNode("", "ccc");
+    addNode("aaa", "aaabbb");
+    addNode("aaa", "aaauuu");
+    addNode("bbb", "bbbuuu");
+}
diff --git a/src/CTree.hpp b/src/CTree.hpp
new file mode 100644
index 0000000..88bccae
--- /dev/null
+++ b/src/CTree.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
+ *
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
+ *
+*/
+
+#pragma once
+
+#include <stdexcept>
+#include <unordered_map>
+#include <unordered_set>
+
+class InvalidNodeException : public std::invalid_argument {
+public:
+    using std::invalid_argument::invalid_argument;
+    ~InvalidNodeException() override;
+
+};
+
+/*! \class CTree
+ *     \brief The class representing the tree, that the user traverses.
+ *
+ *         This class holds the current position in the tree and handles changing the position,
+ *         including checking what nodes are available.
+ *         */
+class CTree {
+public:
+    bool checkNode(const std::string& location, const std::string& node) const;
+    void changeNode(const std::string& node);
+    void initDefault();
+    std::string currentNode() const;
+
+private:
+    void addNode(const std::string& location, const std::string& node);
+    const std::unordered_set<std::string>& children(const std::string& node) const;
+
+    std::unordered_map<std::string, std::unordered_set<std::string>> m_nodes;
+    std::string m_curDir;
+};
diff --git a/src/main.cpp b/src/main.cpp
index 3742e47..7e6d5f1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,22 +2,47 @@
  * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
  * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
  *
- * Written by Jan Kundrát <jan.kundrat@cesnet.cz>
+ * Written by Václav Kubernát <kubervac@fit.cvut.cz>
  *
 */
 
+#include <boost/spirit/home/x3.hpp>
 #include <docopt.h>
+#include <iostream>
 #include <string>
+#include "CParser.hpp"
+#include "CTree.hpp"
 #include "NETCONF_CLI_VERSION.h"
 
+
 static const char usage[] =
-R"(CLI interface to remote NETCONF hosts
+    R"(CLI interface to remote NETCONF hosts
 
 Usage:
+  netconf-cli
   netconf-cli (-h | --help)
   netconf-cli --version
 )";
 
+namespace x3 = boost::spirit::x3;
+namespace ascii = boost::spirit::x3::ascii;
+
+using Cmd = std::vector<std::string>;
+using x3::alpha;
+using x3::lit;
+using x3::char_;
+using x3::_attr;
+using x3::lexeme;
+using ascii::space;
+
+
+std::string getInput()
+{
+    std::string line;
+    std::getline(std::cin, line);
+    return line;
+}
+
 int main(int argc, char* argv[])
 {
     auto args = docopt::docopt(usage,
@@ -25,5 +50,6 @@
                                true,
                                "netconf-cli " NETCONF_CLI_VERSION,
                                true);
+    std::cout << "Welcome to netconf-cli" << std::endl;
     return 0;
 }