Support absolute paths

Change-Id: Ibe087d2bad0c6c9f1619d8811103415bcb3b4906
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 2953dad..aa37574 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -189,6 +189,15 @@
     }
 };
 
+struct absoluteStart_class {
+    template <typename T, typename Iterator, typename Context>
+    void on_success(Iterator const&, Iterator const&, T&, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        parserContext.m_curPath.m_nodes.clear();
+    }
+};
+
 struct path_class {
     template <typename Iterator, typename Exception, typename Context>
     x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
diff --git a/src/ast_path.hpp b/src/ast_path.hpp
index 029d33f..8827a38 100644
--- a/src/ast_path.hpp
+++ b/src/ast_path.hpp
@@ -68,8 +68,15 @@
     bool operator==(const node_& b) const;
 };
 
+enum class Scope
+{
+    Absolute,
+    Relative
+};
+
 struct path_ {
     bool operator==(const path_& b) const;
+    Scope m_scope = Scope::Relative;
     std::vector<node_> m_nodes;
 };
 
@@ -83,4 +90,4 @@
 BOOST_FUSION_ADAPT_STRUCT(listElement_, m_name, m_keys)
 BOOST_FUSION_ADAPT_STRUCT(module_, m_name)
 BOOST_FUSION_ADAPT_STRUCT(node_, m_prefix, m_suffix)
-BOOST_FUSION_ADAPT_STRUCT(path_, m_nodes)
+BOOST_FUSION_ADAPT_STRUCT(path_, m_scope, m_nodes)
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 06e1bf8..ffe6e8b 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -23,6 +23,7 @@
 x3::rule<leaf_class, leaf_> const leaf = "leaf";
 x3::rule<module_class, module_> const module = "module";
 x3::rule<node_class, node_> const node = "node";
+x3::rule<absoluteStart_class, Scope> const absoluteStart = "absoluteStart";
 x3::rule<path_class, path_> const path = "path";
 x3::rule<leaf_path_class, path_> const leafPath = "leafPath";
 
@@ -85,8 +86,13 @@
 auto const node_def =
         -(module) >> x3::expect[container | listElement | nodeup | leaf];
 
+auto const absoluteStart_def =
+        x3::omit['/'] >> x3::attr(Scope::Absolute);
+
+// I have to insert an empty vector to the first alternative, otherwise they won't have the same attribute
 auto const path_def =
-        node % '/';
+        absoluteStart >> x3::attr(decltype(path_::m_nodes)()) >> x3::eoi |
+        -(absoluteStart) >> node % '/';
 
 auto const leafPath_def =
         path;
@@ -159,6 +165,7 @@
 BOOST_SPIRIT_DEFINE(leaf)
 BOOST_SPIRIT_DEFINE(leafPath)
 BOOST_SPIRIT_DEFINE(node)
+BOOST_SPIRIT_DEFINE(absoluteStart)
 BOOST_SPIRIT_DEFINE(path)
 BOOST_SPIRIT_DEFINE(module)
 BOOST_SPIRIT_DEFINE(leaf_data)
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 24c48c4..e3113dd 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -55,7 +55,10 @@
 template <typename T>
 std::string Interpreter::absolutePathFromCommand(const T& command) const
 {
-    return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path));
+    if (command.m_path.m_scope == Scope::Absolute)
+        return "/" + pathToDataString(command.m_path);
+    else
+        return joinPaths(m_parser.currentNode(), pathToDataString(command.m_path));
 }
 
 Interpreter::Interpreter(Parser& parser, DatastoreAccess& datastore)
diff --git a/src/parser.cpp b/src/parser.cpp
index a3550a6..c56b561 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -41,11 +41,15 @@
 
 void Parser::changeNode(const path_& name)
 {
-    for (const auto& it : name.m_nodes) {
-        if (it.m_suffix.type() == typeid(nodeup_))
-            m_curDir.m_nodes.pop_back();
-        else
-            m_curDir.m_nodes.push_back(it);
+    if (name.m_scope == Scope::Absolute) {
+        m_curDir = name;
+    } else {
+        for (const auto& it : name.m_nodes) {
+            if (it.m_suffix.type() == typeid(nodeup_))
+                m_curDir.m_nodes.pop_back();
+            else
+                m_curDir.m_nodes.push_back(it);
+        }
     }
 }
 
diff --git a/src/utils.cpp b/src/utils.cpp
index 9f9fd25..eb48349 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -28,7 +28,7 @@
 
 path_ pathWithoutLastNode(const path_& path)
 {
-    return path_{decltype(path_::m_nodes)(path.m_nodes.begin(), path.m_nodes.end() - 1)};
+    return path_{path.m_scope, decltype(path_::m_nodes)(path.m_nodes.begin(), path.m_nodes.end() - 1)};
 }
 
 std::string leafDataTypeToString(yang::LeafDataTypes type)