blob: 0a7e4657ffb881a0face697cb1d20d999a11edf2 [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át882174d2020-03-25 21:31:46 +010020using x3::char_;
21
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010022struct bool_symbol_table : x3::symbols<bool> {
23 bool_symbol_table()
24 {
Václav Kubernát3a99f002020-03-31 02:27:41 +020025 add
26 ("true", true)
27 ("false", false);
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010028 }
Václav Kubernát882174d2020-03-25 21:31:46 +010029} const bool_symbols;
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010030
Václav Kubernát52b90222022-04-27 11:29:54 +020031auto const leaf_data_string = x3::rule<struct leaf_data_class<yang::String>, std::string>{"leaf_data_string"} =
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010032 '\'' >> *(char_-'\'') >> '\'' |
33 '\"' >> *(char_-'\"') >> '\"';
34
Václav Kubernát52b90222022-04-27 11:29:54 +020035auto const leaf_data_binary = x3::rule<struct leaf_data_class<yang::Binary>, binary_>{"leaf_data_binary"} =
Václav Kubernáte118f002020-05-14 22:54:13 +020036 as<std::string>[+(x3::alnum | char_('+') | char_('/')) >> -char_('=') >> -char_('=')];
Václav Kubernát9ae8cc42020-03-25 19:17:41 +010037
Václav Kubernát52b90222022-04-27 11:29:54 +020038auto const leaf_data_identityRef = x3::rule<struct leaf_data_class<yang::IdentityRef>, identityRef_>{"leaf_data_identityRef"} =
Václav Kubernáte7f62ae2020-05-14 22:57:53 +020039 -module >> node_identifier;
Václav Kubernát3a99f002020-03-31 02:27:41 +020040
41template <typename It, typename Ctx, typename RCtx, typename Attr>
Jan Kundrátbb7aa852023-08-30 11:51:43 +020042bool leaf_data_parse_data_path(It& first, It last, Ctx const& ctx, RCtx& rctx, Attr& attr);
43
44template <typename It, typename Ctx, typename RCtx, typename Attr>
Václav Kubernát3a99f002020-03-31 02:27:41 +020045struct impl_LeafData {
46 It& first;
47 It last;
48 Ctx const& ctx;
49 RCtx& rctx;
50 Attr& attr;
51 ParserContext& parserContext;
52
53 bool operator()(const yang::Binary&) const
54 {
55 return leaf_data_binary.parse(first, last, ctx, rctx, attr);
56 }
57 bool operator()(const yang::Bool&) const
58 {
59 return bool_symbols.parse(first, last, ctx, rctx, attr);
60 }
61 bool operator()(const yang::Decimal&) const
62 {
63 return x3::double_.parse(first, last, ctx, rctx, attr);
64 }
65 bool operator()(const yang::Uint8&) const
66 {
67 return x3::uint8.parse(first, last, ctx, rctx, attr);
68 }
69 bool operator()(const yang::Uint16&) const
70 {
71 return x3::uint16.parse(first, last, ctx, rctx, attr);
72 }
73 bool operator()(const yang::Uint32&) const
74 {
75 return x3::uint32.parse(first, last, ctx, rctx, attr);
76 }
77 bool operator()(const yang::Uint64&) const
78 {
79 return x3::uint64.parse(first, last, ctx, rctx, attr);
80 }
81 bool operator()(const yang::Int8&) const
82 {
83 return x3::int8.parse(first, last, ctx, rctx, attr);
84 }
85 bool operator()(const yang::Int16&) const
86 {
87 return x3::int16.parse(first, last, ctx, rctx, attr);
88 }
89 bool operator()(const yang::Int32&) const
90 {
91 return x3::int32.parse(first, last, ctx, rctx, attr);
92 }
93 bool operator()(const yang::Int64&) const
94 {
95 return x3::int64.parse(first, last, ctx, rctx, attr);
96 }
97 bool operator()(const yang::String&) const
98 {
99 return leaf_data_string.parse(first, last, ctx, rctx, attr);
100 }
Jan Kundrátbb7aa852023-08-30 11:51:43 +0200101 bool operator()(const yang::InstanceIdentifier&) const
102 {
103 return leaf_data_parse_data_path(first, last, ctx, rctx, attr);
104 }
Jan Kundrát379bb572020-05-07 03:23:13 +0200105 bool operator()(const yang::Empty) const
106 {
107 return x3::attr(empty_{}).parse(first, last, ctx, rctx, attr);
108 }
Václav Kubernát3a99f002020-03-31 02:27:41 +0200109 template <typename Type>
110 void createSetSuggestions(const Type& type) const
111 {
112 parserContext.m_suggestions.clear();
113 std::transform(type.m_allowedValues.begin(),
114 type.m_allowedValues.end(),
115 std::inserter(parserContext.m_suggestions, parserContext.m_suggestions.end()),
Václav Kubernát549b08f2020-05-14 22:19:36 +0200116 [](auto it) {
117 std::string res;
118 if constexpr (std::is_same<Type, yang::IdentityRef>()) {
119 res = it.m_prefix ? it.m_prefix->m_name + ":" : "";
120 }
121 res += it.m_value;
122 return Completion{res};
123 });
Václav Kubernát3a99f002020-03-31 02:27:41 +0200124 parserContext.m_completionIterator = first;
125 }
126 bool operator()(const yang::Enum& type) const
127 {
128 createSetSuggestions(type);
Václav Kubernát0af72572020-07-22 15:15:59 +0200129 x3::symbols<enum_> parser;
130 for (const auto& value : type.m_allowedValues) {
131 parser.add(value.m_value, value);
132 }
133 auto res = parser.parse(first, last, ctx, rctx, attr);
134 if (!res) {
135 parserContext.m_errorMsg = "leaf data type mismatch: Expected an enum here. Allowed values:";
136 for (const auto& it : type.m_allowedValues) {
137 parserContext.m_errorMsg += " " + it.m_value;
Václav Kubernát3a99f002020-03-31 02:27:41 +0200138 }
Václav Kubernát0af72572020-07-22 15:15:59 +0200139 }
140 return res;
Václav Kubernát3a99f002020-03-31 02:27:41 +0200141 }
142 bool operator()(const yang::IdentityRef& type) const
143 {
144 createSetSuggestions(type);
Václav Kubernátb4e5b182020-11-16 19:55:09 +0100145 auto checkValidIdentity = [this, type](auto& ctx) {
Václav Kubernáta68c0ef2020-05-07 10:32:56 +0200146 identityRef_ pair{boost::get<identityRef_>(_attr(ctx))};
147 if (!pair.m_prefix) {
148 pair.m_prefix = module_{parserContext.currentSchemaPath().m_nodes.front().m_prefix.get().m_name};
149 }
150 _pass(ctx) = type.m_allowedValues.count(pair) != 0;
151 };
152
153 return leaf_data_identityRef[checkValidIdentity].parse(first, last, ctx, rctx, attr);
Václav Kubernát3a99f002020-03-31 02:27:41 +0200154 }
155 bool operator()(const yang::LeafRef& leafRef) const
156 {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200157 return std::visit(*this, leafRef.m_targetType->m_type);
Václav Kubernát3a99f002020-03-31 02:27:41 +0200158 }
Václav Kubernátdab73ca2020-10-26 23:44:43 +0100159 bool operator()(const yang::Bits& bits) const
160 {
161 parserContext.m_suggestions.clear();
162 x3::symbols<std::string> parser;
163 for (const auto& bit : bits.m_allowedValues) {
164 parser.add(bit, bit);
165 parserContext.m_suggestions.insert(Completion{bit});
166 }
Václav Kubernát467c22c2020-12-03 12:04:04 +0100167 parserContext.m_completionIterator = first;
Václav Kubernátdab73ca2020-10-26 23:44:43 +0100168
169 std::vector<std::string> bitsRes;
170
171 do {
172 std::string bit;
173 auto pass = parser.parse(first, last, ctx, rctx, bit);
174 if (pass) {
175 bitsRes.push_back(bit);
176 parser.remove(bit);
177 parserContext.m_suggestions.erase(Completion{bit});
178 }
179 } while (space_separator.parse(first, last, ctx, rctx, x3::unused));
180
181 attr = bits_{bitsRes};
182
183 return true;
184 }
Václav Kubernát2984f442020-02-20 17:43:35 +0100185 bool operator()(const yang::Union& unionInfo) const
186 {
187 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 +0200188 return std::visit(*this, type.m_type);
Václav Kubernát2984f442020-02-20 17:43:35 +0100189 });
190 }
Václav Kubernát3a99f002020-03-31 02:27:41 +0200191};
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100192
Václav Kubernát882174d2020-03-25 21:31:46 +0100193struct LeafData : x3::parser<LeafData> {
194 using attribute_type = leaf_data_;
Václav Kubernát9ae8cc42020-03-25 19:17:41 +0100195
Václav Kubernát882174d2020-03-25 21:31:46 +0100196 // TODO: Can this be placed in a .cpp file?
197 template <typename It, typename Ctx, typename RCtx, typename Attr>
198 bool parse(It& first, It last, Ctx const& ctx, RCtx& rctx, Attr& attr) const
199 {
200 ParserContext& parserContext = x3::get<parser_context_tag>(ctx);
201 const Schema& schema = parserContext.m_schema;
Václav Kubernát13b23d72020-04-16 21:49:51 +0200202 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 +0100203
Václav Kubernát3a99f002020-03-31 02:27:41 +0200204 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 +0100205
206 if (!pass) {
207 if (parserContext.m_errorMsg.empty()) {
Václav Kubernát13b23d72020-04-16 21:49:51 +0200208 parserContext.m_errorMsg = "leaf data type mismatch: Expected " + leafDataTypeToString(type) + " here:";
Václav Kubernát882174d2020-03-25 21:31:46 +0100209 }
210 }
211 return pass;
212 }
213};
214
Václav Kubernát76bb8c22022-01-19 01:32:31 +0100215auto const leaf_data = LeafData();