Split path_ into schemaPath_ and dataPath_

This change is necessary because different commands accept different
kinds of paths (for example "cd" only accepts a data path, on the other
hand "ls" doesn't care about data, so it accepts both). One option was to
create a new path struct for every command, but that could get quickly
out of control as new commands get added. The other option was define only
the data path and schema path and then change the commands' grammars, so
that they only accept the relevant paths, but in the end always return a
data path or a schema path.

Change-Id: I7668a446fbf674c7a5deae22d9aacdfb3da9b07e
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index b19ece0..c670168 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -121,7 +121,18 @@
         }
     }
 };
+struct list_class {
+    template <typename T, typename Iterator, typename Context>
+    void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        const Schema& schema = parserContext.m_schema;
 
+        if (!schema.isList(parserContext.m_curPath, {parserContext.m_curModule, ast.m_name})) {
+            _pass(context) = false;
+        }
+    }
+};
 struct nodeup_class {
     template <typename T, typename Iterator, typename Context>
     void on_success(Iterator const&, Iterator const&, T&, Context const& context)
@@ -157,7 +168,6 @@
     }
 };
 
-
 struct module_class {
     template <typename T, typename Iterator, typename Context>
     void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
@@ -175,7 +185,7 @@
     }
 };
 
-struct node_class {
+struct schemaNode_class {
     template <typename T, typename Iterator, typename Context>
     void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
     {
@@ -191,6 +201,22 @@
     }
 };
 
+struct dataNode_class {
+    template <typename T, typename Iterator, typename Context>
+    void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        if (ast.m_suffix.type() == typeid(nodeup_)) {
+            parserContext.m_curPath.m_nodes.pop_back();
+            if (parserContext.m_curPath.m_nodes.empty())
+                parserContext.m_topLevelModulePresent = false;
+        } else {
+            parserContext.m_curPath.m_nodes.push_back(dataNodeToSchemaNode(ast));
+            parserContext.m_curModule = boost::none;
+        }
+    }
+};
+
 struct absoluteStart_class {
     template <typename T, typename Iterator, typename Context>
     void on_success(Iterator const&, Iterator const&, T&, Context const& context)
@@ -200,7 +226,21 @@
     }
 };
 
-struct path_class {
+struct dataPath_class {
+    template <typename Iterator, typename Exception, typename Context>
+    x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
+    {
+        auto& parserContext = x3::get<parser_context_tag>(context);
+        if (parserContext.m_errorMsg.empty()) {
+            parserContext.m_errorMsg = "Expected path.";
+            return x3::error_handler_result::fail;
+        } else {
+            return x3::error_handler_result::rethrow;
+        }
+    }
+};
+
+struct schemaPath_class {
     template <typename Iterator, typename Exception, typename Context>
     x3::error_handler_result on_error(Iterator&, Iterator const&, Exception const&, Context const& context)
     {
@@ -240,7 +280,7 @@
             if (ast.m_path.m_nodes.back().m_prefix)
                 module = ast.m_path.m_nodes.back().m_prefix.value().m_name;
             container_ cont = boost::get<container_>(ast.m_path.m_nodes.back().m_suffix);
-            path_ location = pathWithoutLastNode(parserContext.m_curPath);
+            schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
 
             if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
                 parserContext.m_errorMsg = "This container is not a presence container.";
@@ -290,7 +330,10 @@
         auto& schema = parserContext.m_schema;
         if (parserContext.m_errorMsg.empty()) {
             leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
-            path_ location = pathWithoutLastNode(parserContext.m_curPath);
+            schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
+            if (location.m_nodes.empty()) {
+               parserContext.m_curModule = parserContext.m_curPath.m_nodes.back().m_prefix->m_name;
+            }
             parserContext.m_errorMsg = "Expected " + leafDataTypeToString(schema.leafType(location, {parserContext.m_curModule, leaf.m_name})) + " here:";
             return x3::error_handler_result::fail;
         }
@@ -316,7 +359,7 @@
             module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
 
         leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
-        path_ location = pathWithoutLastNode(parserContext.m_curPath);
+        schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
 
         if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
             _pass(context) = false;
@@ -341,7 +384,7 @@
             module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
 
         leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
-        path_ location = pathWithoutLastNode(parserContext.m_curPath);
+        schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
 
         if (!schema.leafEnumHasValue(location, {module, leaf.m_name}, ast.m_value)) {
             _pass(context) = false;