blob: e945fdaa0ad630f74ae15b9940906afa345491ba [file] [log] [blame]
Václav Kubernát9ae8cc42020-03-25 19:17:41 +01001/*
2 * Copyright (C) 2020 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Václav Kubernát <kubernat@cesnet.cz>
5 *
6*/
7
8#pragma once
9
10#include <boost/spirit/home/x3.hpp>
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010011#include "ast_handlers.hpp"
12#include "common_parsers.hpp"
Václav Kubernát3a99f002020-03-31 02:27:41 +020013#include "leaf_data_type.hpp"
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010014#include "schema.hpp"
15namespace x3 = boost::spirit::x3;
16
Václav Kubernát3a99f002020-03-31 02:27:41 +020017template <typename TYPE>
Václav Kubernát882174d2020-03-25 21:31:46 +010018struct leaf_data_class;
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010019
Václav Kubernát3a99f002020-03-31 02:27:41 +020020x3::rule<struct leaf_data_class<yang::IdentityRef>, identityRef_> const leaf_data_identityRef = "leaf_data_identityRef";
21x3::rule<struct leaf_data_class<yang::Binary>, binary_> const leaf_data_binary = "leaf_data_binary";
Václav Kubernát3a99f002020-03-31 02:27:41 +020022x3::rule<struct leaf_data_class<yang::String>, std::string> const leaf_data_string = "leaf_data_string";
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010023
Václav Kubernát882174d2020-03-25 21:31:46 +010024using x3::char_;
25
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010026struct bool_symbol_table : x3::symbols<bool> {
27 bool_symbol_table()
28 {
Václav Kubernát3a99f002020-03-31 02:27:41 +020029 add
30 ("true", true)
31 ("false", false);
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010032 }
Václav Kubernát882174d2020-03-25 21:31:46 +010033} const bool_symbols;
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010034
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010035auto const leaf_data_string_def =
36 '\'' >> *(char_-'\'') >> '\'' |
37 '\"' >> *(char_-'\"') >> '\"';
38
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010039auto const leaf_data_binary_def =
Václav Kubernáte118f002020-05-14 22:54:13 +020040 as<std::string>[+(x3::alnum | char_('+') | char_('/')) >> -char_('=') >> -char_('=')];
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010041
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010042auto const leaf_data_identityRef_def =
Václav Kubernáte7f62ae2020-05-14 22:57:53 +020043 -module >> node_identifier;
Václav Kubernát3a99f002020-03-31 02:27:41 +020044
45template <typename It, typename Ctx, typename RCtx, typename Attr>
46struct impl_LeafData {
47 It& first;
48 It last;
49 Ctx const& ctx;
50 RCtx& rctx;
51 Attr& attr;
52 ParserContext& parserContext;
53
54 bool operator()(const yang::Binary&) const
55 {
56 return leaf_data_binary.parse(first, last, ctx, rctx, attr);
57 }
58 bool operator()(const yang::Bool&) const
59 {
60 return bool_symbols.parse(first, last, ctx, rctx, attr);
61 }
62 bool operator()(const yang::Decimal&) const
63 {
64 return x3::double_.parse(first, last, ctx, rctx, attr);
65 }
66 bool operator()(const yang::Uint8&) const
67 {
68 return x3::uint8.parse(first, last, ctx, rctx, attr);
69 }
70 bool operator()(const yang::Uint16&) const
71 {
72 return x3::uint16.parse(first, last, ctx, rctx, attr);
73 }
74 bool operator()(const yang::Uint32&) const
75 {
76 return x3::uint32.parse(first, last, ctx, rctx, attr);
77 }
78 bool operator()(const yang::Uint64&) const
79 {
80 return x3::uint64.parse(first, last, ctx, rctx, attr);
81 }
82 bool operator()(const yang::Int8&) const
83 {
84 return x3::int8.parse(first, last, ctx, rctx, attr);
85 }
86 bool operator()(const yang::Int16&) const
87 {
88 return x3::int16.parse(first, last, ctx, rctx, attr);
89 }
90 bool operator()(const yang::Int32&) const
91 {
92 return x3::int32.parse(first, last, ctx, rctx, attr);
93 }
94 bool operator()(const yang::Int64&) const
95 {
96 return x3::int64.parse(first, last, ctx, rctx, attr);
97 }
98 bool operator()(const yang::String&) const
99 {
100 return leaf_data_string.parse(first, last, ctx, rctx, attr);
101 }
Jan Kundrát379bb572020-05-07 03:23:13 +0200102 bool operator()(const yang::Empty) const
103 {
104 return x3::attr(empty_{}).parse(first, last, ctx, rctx, attr);
105 }
Václav Kubernát3a99f002020-03-31 02:27:41 +0200106 template <typename Type>
107 void createSetSuggestions(const Type& type) const
108 {
109 parserContext.m_suggestions.clear();
110 std::transform(type.m_allowedValues.begin(),
111 type.m_allowedValues.end(),
112 std::inserter(parserContext.m_suggestions, parserContext.m_suggestions.end()),
Václav Kubernát549b08f2020-05-14 22:19:36 +0200113 [](auto it) {
114 std::string res;
115 if constexpr (std::is_same<Type, yang::IdentityRef>()) {
116 res = it.m_prefix ? it.m_prefix->m_name + ":" : "";
117 }
118 res += it.m_value;
119 return Completion{res};
120 });
Václav Kubernát3a99f002020-03-31 02:27:41 +0200121 parserContext.m_completionIterator = first;
122 }
123 bool operator()(const yang::Enum& type) const
124 {
125 createSetSuggestions(type);
Václav Kubernát0af72572020-07-22 15:15:59 +0200126 x3::symbols<enum_> parser;
127 for (const auto& value : type.m_allowedValues) {
128 parser.add(value.m_value, value);
129 }
130 auto res = parser.parse(first, last, ctx, rctx, attr);
131 if (!res) {
132 parserContext.m_errorMsg = "leaf data type mismatch: Expected an enum here. Allowed values:";
133 for (const auto& it : type.m_allowedValues) {
134 parserContext.m_errorMsg += " " + it.m_value;
Václav Kubernát3a99f002020-03-31 02:27:41 +0200135 }
Václav Kubernát0af72572020-07-22 15:15:59 +0200136 }
137 return res;
Václav Kubernát3a99f002020-03-31 02:27:41 +0200138 }
139 bool operator()(const yang::IdentityRef& type) const
140 {
141 createSetSuggestions(type);
Václav Kubernátb4e5b182020-11-16 19:55:09 +0100142 auto checkValidIdentity = [this, type](auto& ctx) {
Václav Kubernáta68c0ef2020-05-07 10:32:56 +0200143 identityRef_ pair{boost::get<identityRef_>(_attr(ctx))};
144 if (!pair.m_prefix) {
145 pair.m_prefix = module_{parserContext.currentSchemaPath().m_nodes.front().m_prefix.get().m_name};
146 }
147 _pass(ctx) = type.m_allowedValues.count(pair) != 0;
148 };
149
150 return leaf_data_identityRef[checkValidIdentity].parse(first, last, ctx, rctx, attr);
Václav Kubernát3a99f002020-03-31 02:27:41 +0200151 }
152 bool operator()(const yang::LeafRef& leafRef) const
153 {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200154 return std::visit(*this, leafRef.m_targetType->m_type);
Václav Kubernát3a99f002020-03-31 02:27:41 +0200155 }
Václav Kubernátdab73ca2020-10-26 23:44:43 +0100156 bool operator()(const yang::Bits& bits) const
157 {
158 parserContext.m_suggestions.clear();
159 x3::symbols<std::string> parser;
160 for (const auto& bit : bits.m_allowedValues) {
161 parser.add(bit, bit);
162 parserContext.m_suggestions.insert(Completion{bit});
163 }
Václav Kubernát467c22c2020-12-03 12:04:04 +0100164 parserContext.m_completionIterator = first;
Václav Kubernátdab73ca2020-10-26 23:44:43 +0100165
166 std::vector<std::string> bitsRes;
167
168 do {
169 std::string bit;
170 auto pass = parser.parse(first, last, ctx, rctx, bit);
171 if (pass) {
172 bitsRes.push_back(bit);
173 parser.remove(bit);
174 parserContext.m_suggestions.erase(Completion{bit});
175 }
176 } while (space_separator.parse(first, last, ctx, rctx, x3::unused));
177
178 attr = bits_{bitsRes};
179
180 return true;
181 }
Václav Kubernát2984f442020-02-20 17:43:35 +0100182 bool operator()(const yang::Union& unionInfo) const
183 {
184 return std::any_of(unionInfo.m_unionTypes.begin(), unionInfo.m_unionTypes.end(), [this](const auto& type) {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200185 return std::visit(*this, type.m_type);
Václav Kubernát2984f442020-02-20 17:43:35 +0100186 });
187 }
Václav Kubernát3a99f002020-03-31 02:27:41 +0200188};
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100189
Václav Kubernát882174d2020-03-25 21:31:46 +0100190struct LeafData : x3::parser<LeafData> {
191 using attribute_type = leaf_data_;
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100192
Václav Kubernát882174d2020-03-25 21:31:46 +0100193 // TODO: Can this be placed in a .cpp file?
194 template <typename It, typename Ctx, typename RCtx, typename Attr>
195 bool parse(It& first, It last, Ctx const& ctx, RCtx& rctx, Attr& attr) const
196 {
197 ParserContext& parserContext = x3::get<parser_context_tag>(ctx);
198 const Schema& schema = parserContext.m_schema;
Václav Kubernát13b23d72020-04-16 21:49:51 +0200199 auto type = schema.leafType(parserContext.m_tmpListKeyLeafPath.m_location, parserContext.m_tmpListKeyLeafPath.m_node).m_type;
Václav Kubernát882174d2020-03-25 21:31:46 +0100200
Václav Kubernát3a99f002020-03-31 02:27:41 +0200201 auto pass = std::visit(impl_LeafData<It, Ctx, RCtx, Attr>{first, last, ctx, rctx, attr, parserContext}, type);
Václav Kubernát882174d2020-03-25 21:31:46 +0100202
203 if (!pass) {
204 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200205 parserContext.m_errorMsg = "leaf data type mismatch: Expected " + leafDataTypeToString(type) + " here:";
Václav Kubernát882174d2020-03-25 21:31:46 +0100206 }
207 }
208 return pass;
209 }
210};
211
Václav Kubernát76bb8c22022-01-19 01:32:31 +0100212auto const leaf_data = LeafData();
Václav Kubernát882174d2020-03-25 21:31:46 +0100213
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100214BOOST_SPIRIT_DEFINE(leaf_data_string)
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100215BOOST_SPIRIT_DEFINE(leaf_data_binary)
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100216BOOST_SPIRIT_DEFINE(leaf_data_identityRef)