Add types for leaves
Change-Id: Ibea2945920e523d2f3439eed2c12a5d719d178f1
diff --git a/src/ast_commands.cpp b/src/ast_commands.cpp
index a8b481d..9ef9044 100644
--- a/src/ast_commands.cpp
+++ b/src/ast_commands.cpp
@@ -7,6 +7,12 @@
*/
#include "ast_commands.hpp"
+enum_::enum_() = default;
+
+enum_::enum_(const std::string& value)
+ : m_value(value)
+{
+}
bool set_::operator==(const set_& b) const
{
@@ -18,6 +24,11 @@
return this->m_path == b.m_path;
}
+bool enum_::operator==(const enum_& b) const
+{
+ return this->m_value == b.m_value;
+}
+
bool create_::operator==(const create_& b) const
{
return this->m_path == b.m_path;
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index 5caeb2e..90af8ea 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -17,9 +17,12 @@
using x3::alnum;
using x3::alpha;
using x3::char_;
+using x3::double_;
using x3::expect;
+using x3::int_;
using x3::lexeme;
using x3::lit;
+using x3::uint_;
struct parser_context_tag;
@@ -40,10 +43,24 @@
path_ m_path;
};
+struct enum_ {
+ enum_();
+ enum_(const std::string& value);
+ bool operator==(const enum_& b) const;
+ std::string m_value;
+};
+
+using leaf_data_ = boost::variant<enum_,
+ double,
+ bool,
+ int32_t,
+ uint32_t,
+ std::string>;
+
struct set_ : x3::position_tagged {
bool operator==(const set_& b) const;
path_ m_path;
- std::string m_data;
+ leaf_data_ m_data;
};
using command_ = boost::variant<cd_, create_, delete_, set_>;
@@ -51,4 +68,5 @@
BOOST_FUSION_ADAPT_STRUCT(cd_, m_path)
BOOST_FUSION_ADAPT_STRUCT(create_, m_path)
BOOST_FUSION_ADAPT_STRUCT(delete_, m_path)
+BOOST_FUSION_ADAPT_STRUCT(enum_, m_value)
BOOST_FUSION_ADAPT_STRUCT(set_, m_path, m_data)
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 0d3159b..848ce21 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -10,6 +10,7 @@
#include "parser_context.hpp"
#include "schema.hpp"
+#include "utils.hpp"
struct keyValue_class {
template <typename T, typename Iterator, typename Context>
@@ -90,7 +91,6 @@
if (parserContext.m_errorMsg.empty())
parserContext.m_errorMsg = "Expecting ']' here:";
return x3::error_handler_result::rethrow;
-
}
};
struct listElement_class {
@@ -110,7 +110,6 @@
} else {
return x3::error_handler_result::rethrow;
}
-
}
};
@@ -177,9 +176,6 @@
}
};
-struct data_string_class {
-};
-
struct cd_class {
template <typename T, typename Iterator, typename Context>
void on_success(Iterator const&, Iterator const&, T&, Context const&)
@@ -204,8 +200,7 @@
const auto& schema = parserContext.m_schema;
try {
container_ cont = boost::get<container_>(ast.m_path.m_nodes.back());
- path_ location{decltype(path_::m_nodes)(parserContext.m_curPath.m_nodes.begin(),
- parserContext.m_curPath.m_nodes.end() - 1)};
+ path_ location = pathWithoutLastNode(parserContext.m_curPath);
if (!schema.isPresenceContainer(location, cont.m_name)) {
parserContext.m_errorMsg = "This container is not a presence container.";
@@ -233,6 +228,89 @@
struct delete_class : public presenceContainerPathHandler {
};
+struct leaf_data_class {
+};
+
+struct leaf_data_base_class {
+ yang::LeafDataTypes m_type;
+
+ leaf_data_base_class(yang::LeafDataTypes type)
+ : m_type(type)
+ {
+ }
+
+ 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);
+ auto& schema = parserContext.m_schema;
+
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
+ path_ location = pathWithoutLastNode(parserContext.m_curPath);
+
+ if (schema.leafType(location, leaf.m_name) != m_type) {
+ _pass(context) = false;
+ }
+ }
+};
+
+struct leaf_data_enum_class : leaf_data_base_class {
+ leaf_data_enum_class()
+ : leaf_data_base_class(yang::LeafDataTypes::Enum)
+ {
+ }
+
+ template <typename T, typename Iterator, typename Context>
+ void on_success(Iterator const& start, Iterator const& end, T& ast, Context const& context)
+ {
+ leaf_data_base_class::on_success(start, end, ast, context);
+ auto& parserContext = x3::get<parser_context_tag>(context);
+ auto& schema = parserContext.m_schema;
+
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back());
+ path_ location = pathWithoutLastNode(parserContext.m_curPath);
+
+ if (!schema.leafEnumHasValue(location, leaf.m_name, ast.m_value)) {
+ _pass(context) = false;
+ }
+ }
+};
+
+struct leaf_data_decimal_class : leaf_data_base_class {
+ leaf_data_decimal_class()
+ : leaf_data_base_class(yang::LeafDataTypes::Decimal)
+ {
+ }
+};
+
+struct leaf_data_bool_class : leaf_data_base_class {
+ leaf_data_bool_class()
+ : leaf_data_base_class(yang::LeafDataTypes::Bool)
+ {
+ }
+};
+
+struct leaf_data_int_class : leaf_data_base_class {
+ leaf_data_int_class()
+ : leaf_data_base_class(yang::LeafDataTypes::Int)
+ {
+ }
+};
+
+struct leaf_data_uint_class : leaf_data_base_class {
+ leaf_data_uint_class()
+ : leaf_data_base_class(yang::LeafDataTypes::Uint)
+ {
+ }
+};
+
+struct leaf_data_string_class : leaf_data_base_class {
+ leaf_data_string_class()
+ : leaf_data_base_class(yang::LeafDataTypes::String)
+ {
+ }
+};
+
struct set_class {
template <typename T, typename Iterator, typename Context>
void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
diff --git a/src/ast_path.cpp b/src/ast_path.cpp
index 2d2c600..2734377 100644
--- a/src/ast_path.cpp
+++ b/src/ast_path.cpp
@@ -69,7 +69,7 @@
std::experimental::make_ostream_joiner(res, ' '),
[] (const auto& it) { return it.first + "=" + it.second; });
res << "]";
- return res.str();
+ return res.str();
}
std::string operator()(const nodeup_&) const
{
diff --git a/src/grammars.hpp b/src/grammars.hpp
index ab410c8..443b28d 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -21,7 +21,15 @@
x3::rule<container_class, container_> const container = "container";
x3::rule<leaf_class, leaf_> const leaf = "leaf";
x3::rule<path_class, path_> const path = "path";
-x3::rule<data_string_class, std::string> const data_string = "data_string";
+
+x3::rule<leaf_data_class, leaf_data_> const leaf_data = "leaf_data";
+x3::rule<leaf_data_enum_class, enum_> const leaf_data_enum = "leaf_data_enum";
+x3::rule<leaf_data_decimal_class, double> const leaf_data_decimal = "leaf_data_decimal";
+x3::rule<leaf_data_bool_class, bool> const leaf_data_bool = "leaf_data_bool";
+x3::rule<leaf_data_int_class, int32_t> const leaf_data_int = "leaf_data_int";
+x3::rule<leaf_data_uint_class, uint32_t> const leaf_data_uint = "leaf_data_uint";
+x3::rule<leaf_data_string_class, std::string> const leaf_data_string = "leaf_data_string";
+
x3::rule<cd_class, cd_> const cd = "cd";
x3::rule<set_class, set_> const set = "set";
x3::rule<create_class, create_> const create = "create";
@@ -64,8 +72,36 @@
auto const path_def =
(x3::expect[container | listElement | nodeup | leaf]) % '/';
-auto const data_string_def =
- lexeme[+char_];
+auto const leaf_data_enum_def =
+ +char_;
+auto const leaf_data_decimal_def =
+ double_;
+
+struct bool_symbol_table : x3::symbols<bool> {
+ bool_symbol_table()
+ {
+ add
+ ("true", true)
+ ("false", false);
+ }
+} const bool_rule;
+
+auto const leaf_data_bool_def =
+ bool_rule;
+auto const leaf_data_int_def =
+ int_;
+auto const leaf_data_uint_def =
+ uint_;
+auto const leaf_data_string_def =
+ *char_;
+
+auto const leaf_data_def =
+ leaf_data_enum |
+ leaf_data_decimal |
+ leaf_data_bool |
+ leaf_data_int |
+ leaf_data_uint |
+ leaf_data_string;
auto const space_separator =
x3::omit[x3::no_skip[space]];
@@ -80,7 +116,7 @@
lit("delete") >> space_separator > path;
auto const set_def =
- lit("set") >> space_separator > path > data_string;
+ lit("set") >> space_separator > path > leaf_data;
auto const command_def =
x3::expect[cd | create | delete_rule | set] >> x3::eoi;
@@ -98,7 +134,13 @@
BOOST_SPIRIT_DEFINE(container)
BOOST_SPIRIT_DEFINE(leaf)
BOOST_SPIRIT_DEFINE(path)
-BOOST_SPIRIT_DEFINE(data_string)
+BOOST_SPIRIT_DEFINE(leaf_data)
+BOOST_SPIRIT_DEFINE(leaf_data_enum)
+BOOST_SPIRIT_DEFINE(leaf_data_decimal)
+BOOST_SPIRIT_DEFINE(leaf_data_bool)
+BOOST_SPIRIT_DEFINE(leaf_data_int)
+BOOST_SPIRIT_DEFINE(leaf_data_uint)
+BOOST_SPIRIT_DEFINE(leaf_data_string)
BOOST_SPIRIT_DEFINE(set)
BOOST_SPIRIT_DEFINE(cd)
BOOST_SPIRIT_DEFINE(create)
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 934aac9..1a4e84a 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -9,9 +9,23 @@
#include <iostream>
#include "interpreter.hpp"
+struct leafDataToString : boost::static_visitor<std::string> {
+ std::string operator()(const enum_& data) const
+ {
+ return data.m_value;
+ }
+ template <typename T>
+ std::string operator()(const T& data) const
+ {
+ std::stringstream stream;
+ stream << data;
+ return stream.str();
+ }
+};
+
void Interpreter::operator()(const set_& set) const
{
- std::cout << "Setting " << pathToDataString(set.m_path) << " to " << set.m_data << std::endl;
+ std::cout << "Setting " << pathToDataString(set.m_path) << " to " << boost::apply_visitor(leafDataToString(), set.m_data) << std::endl;
}
void Interpreter::operator()(const cd_& cd) const
diff --git a/src/main.cpp b/src/main.cpp
index df4c925..e498db0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -49,9 +49,14 @@
Schema schema;
schema.addContainer("", "a", yang::ContainerTraits::Presence);
schema.addContainer("", "b");
- schema.addLeaf("", "leaf");
+ schema.addLeaf("", "leafString", yang::LeafDataTypes::String);
+ schema.addLeaf("", "leafDecimal", yang::LeafDataTypes::Decimal);
+ schema.addLeaf("", "leafBool", yang::LeafDataTypes::Bool);
+ schema.addLeaf("", "leafInt", yang::LeafDataTypes::Int);
+ schema.addLeaf("", "leafUint", yang::LeafDataTypes::Uint);
+ schema.addLeafEnum("", "leafEnum", {"lol", "data", "coze"});
schema.addContainer("a", "a2");
- schema.addLeaf("a", "leafa");
+ schema.addLeaf("a", "leafa", yang::LeafDataTypes::String);
schema.addContainer("b", "b2", yang::ContainerTraits::Presence);
schema.addContainer("a/a2", "a3", yang::ContainerTraits::Presence);
schema.addContainer("b/b2", "b3");
diff --git a/src/schema.cpp b/src/schema.cpp
index 95cd4ae..066dc3b 100644
--- a/src/schema.cpp
+++ b/src/schema.cpp
@@ -96,9 +96,24 @@
return boost::get<yang::container>(children(locationString).at(name)).m_presence == yang::ContainerTraits::Presence;
}
-void Schema::addLeaf(const std::string& location, const std::string& name)
+void Schema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
{
- m_nodes.at(location).emplace(name, yang::leaf{});
+ m_nodes.at(location).emplace(name, yang::leaf{type, {}});
+}
+
+void Schema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
+{
+ m_nodes.at(location).emplace(name, yang::leaf{yang::LeafDataTypes::Enum, enumValues});
+}
+
+bool Schema::leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const
+{
+ std::string locationString = pathToSchemaString(location);
+ assert(isLeaf(location, name));
+
+ const auto& child = children(locationString).at(name);
+ const auto& list = boost::get<yang::leaf>(child);
+ return list.m_enumValues.find(value) != list.m_enumValues.end();
}
bool Schema::isLeaf(const path_& location, const std::string& name) const
@@ -109,3 +124,9 @@
return children(locationString).at(name).type() == typeid(yang::leaf);
}
+
+yang::LeafDataTypes Schema::leafType(const path_& location, const std::string& name) const
+{
+ std::string locationString = pathToSchemaString(location);
+ return boost::get<yang::leaf>(children(locationString).at(name)).m_type;
+}
diff --git a/src/schema.hpp b/src/schema.hpp
index 73e89df..e87619b 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -19,6 +19,16 @@
Presence,
None,
};
+
+enum class LeafDataTypes {
+ String,
+ Decimal,
+ Bool,
+ Int,
+ Uint,
+ Enum,
+};
+
struct container {
yang::ContainerTraits m_presence;
};
@@ -26,6 +36,8 @@
std::set<std::string> m_keys;
};
struct leaf {
+ yang::LeafDataTypes m_type;
+ std::set<std::string> m_enumValues;
};
}
@@ -54,8 +66,11 @@
bool isList(const path_& location, const std::string& name) const;
void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
bool isPresenceContainer(const path_& location, const std::string& name) const;
- void addLeaf(const std::string& location, const std::string& name);
+ void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
+ void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
+ bool leafEnumHasValue(const path_& location, const std::string& name, const std::string& value) const;
bool isLeaf(const path_& location, const std::string& name) const;
+ yang::LeafDataTypes leafType(const path_& location, const std::string& name) const;
private:
const std::unordered_map<std::string, NodeType>& children(const std::string& name) const;
diff --git a/src/utils.cpp b/src/utils.cpp
index 77466c4..a7fea46 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -25,3 +25,8 @@
res.erase(pos);
return res;
}
+
+path_ pathWithoutLastNode(const path_& path)
+{
+ return path_{decltype(path_::m_nodes)(path.m_nodes.begin(), path.m_nodes.end() - 1)};
+}
diff --git a/src/utils.hpp b/src/utils.hpp
index 4f10102..2c550d7 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -6,6 +6,8 @@
*
*/
#include <string>
+#include "ast_path.hpp"
std::string joinPaths(const std::string& prefix, const std::string& suffix);
std::string stripLastNodeFromPath(const std::string& path);
+path_ pathWithoutLastNode(const path_& path);