1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #include "tools/cddl/sema.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <string.h>
8*3f982cf4SFabien Sanglard #include <unistd.h>
9*3f982cf4SFabien Sanglard
10*3f982cf4SFabien Sanglard #include <cinttypes>
11*3f982cf4SFabien Sanglard #include <cstdlib>
12*3f982cf4SFabien Sanglard #include <iostream>
13*3f982cf4SFabien Sanglard #include <map>
14*3f982cf4SFabien Sanglard #include <memory>
15*3f982cf4SFabien Sanglard #include <string>
16*3f982cf4SFabien Sanglard #include <unordered_set>
17*3f982cf4SFabien Sanglard #include <vector>
18*3f982cf4SFabien Sanglard
19*3f982cf4SFabien Sanglard #include "absl/algorithm/container.h"
20*3f982cf4SFabien Sanglard #include "absl/strings/numbers.h"
21*3f982cf4SFabien Sanglard #include "absl/strings/string_view.h"
22*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
23*3f982cf4SFabien Sanglard #include "tools/cddl/logging.h"
24*3f982cf4SFabien Sanglard
TypesWithId()25*3f982cf4SFabien Sanglard std::vector<CppType*> CppSymbolTable::TypesWithId() {
26*3f982cf4SFabien Sanglard if (!this->TypesWithId_.size()) {
27*3f982cf4SFabien Sanglard for (const std::unique_ptr<CppType>& ptr : this->cpp_types) {
28*3f982cf4SFabien Sanglard if (ptr->type_key == absl::nullopt) {
29*3f982cf4SFabien Sanglard continue;
30*3f982cf4SFabien Sanglard }
31*3f982cf4SFabien Sanglard this->TypesWithId_.emplace_back(ptr.get());
32*3f982cf4SFabien Sanglard }
33*3f982cf4SFabien Sanglard }
34*3f982cf4SFabien Sanglard return this->TypesWithId_;
35*3f982cf4SFabien Sanglard }
36*3f982cf4SFabien Sanglard
CddlType()37*3f982cf4SFabien Sanglard CddlType::CddlType()
38*3f982cf4SFabien Sanglard : map(nullptr), op(CddlType::Op::kNone), constraint_type(nullptr) {}
~CddlType()39*3f982cf4SFabien Sanglard CddlType::~CddlType() {
40*3f982cf4SFabien Sanglard switch (which) {
41*3f982cf4SFabien Sanglard case CddlType::Which::kDirectChoice:
42*3f982cf4SFabien Sanglard direct_choice.std::vector<CddlType*>::~vector();
43*3f982cf4SFabien Sanglard break;
44*3f982cf4SFabien Sanglard case CddlType::Which::kValue:
45*3f982cf4SFabien Sanglard value.std::string::~basic_string();
46*3f982cf4SFabien Sanglard break;
47*3f982cf4SFabien Sanglard case CddlType::Which::kId:
48*3f982cf4SFabien Sanglard id.std::string::~basic_string();
49*3f982cf4SFabien Sanglard break;
50*3f982cf4SFabien Sanglard case CddlType::Which::kMap:
51*3f982cf4SFabien Sanglard break;
52*3f982cf4SFabien Sanglard case CddlType::Which::kArray:
53*3f982cf4SFabien Sanglard break;
54*3f982cf4SFabien Sanglard case CddlType::Which::kGroupChoice:
55*3f982cf4SFabien Sanglard break;
56*3f982cf4SFabien Sanglard case CddlType::Which::kGroupnameChoice:
57*3f982cf4SFabien Sanglard break;
58*3f982cf4SFabien Sanglard case CddlType::Which::kTaggedType:
59*3f982cf4SFabien Sanglard tagged_type.~TaggedType();
60*3f982cf4SFabien Sanglard break;
61*3f982cf4SFabien Sanglard }
62*3f982cf4SFabien Sanglard }
63*3f982cf4SFabien Sanglard
Entry()64*3f982cf4SFabien Sanglard CddlGroup::Entry::Entry() : group(nullptr) {}
~Entry()65*3f982cf4SFabien Sanglard CddlGroup::Entry::~Entry() {
66*3f982cf4SFabien Sanglard switch (which) {
67*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kUninitialized:
68*3f982cf4SFabien Sanglard break;
69*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kType:
70*3f982cf4SFabien Sanglard type.~EntryType();
71*3f982cf4SFabien Sanglard break;
72*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kGroup:
73*3f982cf4SFabien Sanglard break;
74*3f982cf4SFabien Sanglard }
75*3f982cf4SFabien Sanglard }
76*3f982cf4SFabien Sanglard
CppType()77*3f982cf4SFabien Sanglard CppType::CppType() : vector_type() {}
~CppType()78*3f982cf4SFabien Sanglard CppType::~CppType() {
79*3f982cf4SFabien Sanglard switch (which) {
80*3f982cf4SFabien Sanglard case CppType::Which::kUninitialized:
81*3f982cf4SFabien Sanglard break;
82*3f982cf4SFabien Sanglard case CppType::Which::kUint64:
83*3f982cf4SFabien Sanglard break;
84*3f982cf4SFabien Sanglard case CppType::Which::kString:
85*3f982cf4SFabien Sanglard break;
86*3f982cf4SFabien Sanglard case CppType::Which::kBytes:
87*3f982cf4SFabien Sanglard break;
88*3f982cf4SFabien Sanglard case CppType::Which::kVector:
89*3f982cf4SFabien Sanglard break;
90*3f982cf4SFabien Sanglard case CppType::Which::kEnum:
91*3f982cf4SFabien Sanglard enum_type.~Enum();
92*3f982cf4SFabien Sanglard break;
93*3f982cf4SFabien Sanglard case CppType::Which::kStruct:
94*3f982cf4SFabien Sanglard struct_type.~Struct();
95*3f982cf4SFabien Sanglard break;
96*3f982cf4SFabien Sanglard case CppType::Which::kOptional:
97*3f982cf4SFabien Sanglard break;
98*3f982cf4SFabien Sanglard case CppType::Which::kDiscriminatedUnion:
99*3f982cf4SFabien Sanglard discriminated_union.~DiscriminatedUnion();
100*3f982cf4SFabien Sanglard break;
101*3f982cf4SFabien Sanglard case CppType::Which::kTaggedType:
102*3f982cf4SFabien Sanglard break;
103*3f982cf4SFabien Sanglard }
104*3f982cf4SFabien Sanglard }
105*3f982cf4SFabien Sanglard
InitVector()106*3f982cf4SFabien Sanglard void CppType::InitVector() {
107*3f982cf4SFabien Sanglard which = Which::kVector;
108*3f982cf4SFabien Sanglard new (&vector_type) Vector();
109*3f982cf4SFabien Sanglard }
110*3f982cf4SFabien Sanglard
InitEnum()111*3f982cf4SFabien Sanglard void CppType::InitEnum() {
112*3f982cf4SFabien Sanglard which = Which::kEnum;
113*3f982cf4SFabien Sanglard new (&enum_type) Enum();
114*3f982cf4SFabien Sanglard }
115*3f982cf4SFabien Sanglard
InitStruct()116*3f982cf4SFabien Sanglard void CppType::InitStruct() {
117*3f982cf4SFabien Sanglard which = Which::kStruct;
118*3f982cf4SFabien Sanglard new (&struct_type) Struct();
119*3f982cf4SFabien Sanglard }
120*3f982cf4SFabien Sanglard
InitDiscriminatedUnion()121*3f982cf4SFabien Sanglard void CppType::InitDiscriminatedUnion() {
122*3f982cf4SFabien Sanglard which = Which::kDiscriminatedUnion;
123*3f982cf4SFabien Sanglard new (&discriminated_union) DiscriminatedUnion();
124*3f982cf4SFabien Sanglard }
125*3f982cf4SFabien Sanglard
InitBytes()126*3f982cf4SFabien Sanglard void CppType::InitBytes() {
127*3f982cf4SFabien Sanglard which = Which::kBytes;
128*3f982cf4SFabien Sanglard }
129*3f982cf4SFabien Sanglard
InitString(std::string * s,absl::string_view value)130*3f982cf4SFabien Sanglard void InitString(std::string* s, absl::string_view value) {
131*3f982cf4SFabien Sanglard new (s) std::string(value);
132*3f982cf4SFabien Sanglard }
133*3f982cf4SFabien Sanglard
InitDirectChoice(std::vector<CddlType * > * direct_choice)134*3f982cf4SFabien Sanglard void InitDirectChoice(std::vector<CddlType*>* direct_choice) {
135*3f982cf4SFabien Sanglard new (direct_choice) std::vector<CddlType*>();
136*3f982cf4SFabien Sanglard }
137*3f982cf4SFabien Sanglard
InitGroupEntry(CddlGroup::Entry::EntryType * entry)138*3f982cf4SFabien Sanglard void InitGroupEntry(CddlGroup::Entry::EntryType* entry) {
139*3f982cf4SFabien Sanglard new (entry) CddlGroup::Entry::EntryType();
140*3f982cf4SFabien Sanglard }
141*3f982cf4SFabien Sanglard
AddCddlType(CddlSymbolTable * table,CddlType::Which which)142*3f982cf4SFabien Sanglard CddlType* AddCddlType(CddlSymbolTable* table, CddlType::Which which) {
143*3f982cf4SFabien Sanglard table->types.emplace_back(new CddlType);
144*3f982cf4SFabien Sanglard CddlType* value = table->types.back().get();
145*3f982cf4SFabien Sanglard value->which = which;
146*3f982cf4SFabien Sanglard return value;
147*3f982cf4SFabien Sanglard }
148*3f982cf4SFabien Sanglard
149*3f982cf4SFabien Sanglard CddlType* AnalyzeType(CddlSymbolTable* table, const AstNode& type);
150*3f982cf4SFabien Sanglard CddlGroup* AnalyzeGroup(CddlSymbolTable* table, const AstNode& group);
151*3f982cf4SFabien Sanglard
AnalyzeType2(CddlSymbolTable * table,const AstNode & type2)152*3f982cf4SFabien Sanglard CddlType* AnalyzeType2(CddlSymbolTable* table, const AstNode& type2) {
153*3f982cf4SFabien Sanglard const AstNode* node = type2.children;
154*3f982cf4SFabien Sanglard if (node->type == AstNode::Type::kNumber ||
155*3f982cf4SFabien Sanglard node->type == AstNode::Type::kText ||
156*3f982cf4SFabien Sanglard node->type == AstNode::Type::kBytes) {
157*3f982cf4SFabien Sanglard CddlType* value = AddCddlType(table, CddlType::Which::kValue);
158*3f982cf4SFabien Sanglard InitString(&value->value, node->text);
159*3f982cf4SFabien Sanglard return value;
160*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kTypename) {
161*3f982cf4SFabien Sanglard if (type2.text[0] == '~') {
162*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "We don't support the '~' operator.\n");
163*3f982cf4SFabien Sanglard return nullptr;
164*3f982cf4SFabien Sanglard }
165*3f982cf4SFabien Sanglard CddlType* id = AddCddlType(table, CddlType::Which::kId);
166*3f982cf4SFabien Sanglard InitString(&id->id, node->text);
167*3f982cf4SFabien Sanglard return id;
168*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kType) {
169*3f982cf4SFabien Sanglard if (type2.text[0] == '#' && type2.text[1] == '6' && type2.text[2] == '.') {
170*3f982cf4SFabien Sanglard CddlType* tagged_type = AddCddlType(table, CddlType::Which::kTaggedType);
171*3f982cf4SFabien Sanglard tagged_type->tagged_type.tag_value =
172*3f982cf4SFabien Sanglard atoll(type2.text.substr(3 /* #6. */).data());
173*3f982cf4SFabien Sanglard tagged_type->tagged_type.type = AnalyzeType(table, *node);
174*3f982cf4SFabien Sanglard return tagged_type;
175*3f982cf4SFabien Sanglard }
176*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Unknown type2 value, expected #6.[uint]\n");
177*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kGroup) {
178*3f982cf4SFabien Sanglard if (type2.text[0] == '{') {
179*3f982cf4SFabien Sanglard CddlType* map = AddCddlType(table, CddlType::Which::kMap);
180*3f982cf4SFabien Sanglard map->map = AnalyzeGroup(table, *node);
181*3f982cf4SFabien Sanglard return map;
182*3f982cf4SFabien Sanglard } else if (type2.text[0] == '[') {
183*3f982cf4SFabien Sanglard CddlType* array = AddCddlType(table, CddlType::Which::kArray);
184*3f982cf4SFabien Sanglard array->array = AnalyzeGroup(table, *node);
185*3f982cf4SFabien Sanglard return array;
186*3f982cf4SFabien Sanglard } else if (type2.text[0] == '&') {
187*3f982cf4SFabien Sanglard // Represents a choice between options in this group (ie an enum), not a
188*3f982cf4SFabien Sanglard // choice between groups (which is currently unsupported).
189*3f982cf4SFabien Sanglard CddlType* group_choice =
190*3f982cf4SFabien Sanglard AddCddlType(table, CddlType::Which::kGroupChoice);
191*3f982cf4SFabien Sanglard group_choice->group_choice = AnalyzeGroup(table, *node);
192*3f982cf4SFabien Sanglard return group_choice;
193*3f982cf4SFabien Sanglard }
194*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kGroupname) {
195*3f982cf4SFabien Sanglard if (type2.text[0] == '&') {
196*3f982cf4SFabien Sanglard CddlType* group_choice =
197*3f982cf4SFabien Sanglard AddCddlType(table, CddlType::Which::kGroupnameChoice);
198*3f982cf4SFabien Sanglard InitString(&group_choice->id, node->text);
199*3f982cf4SFabien Sanglard return group_choice;
200*3f982cf4SFabien Sanglard }
201*3f982cf4SFabien Sanglard }
202*3f982cf4SFabien Sanglard return nullptr;
203*3f982cf4SFabien Sanglard }
204*3f982cf4SFabien Sanglard
AnalyzeRangeop(const AstNode & rangeop)205*3f982cf4SFabien Sanglard CddlType::Op AnalyzeRangeop(const AstNode& rangeop) {
206*3f982cf4SFabien Sanglard if (rangeop.text == "..") {
207*3f982cf4SFabien Sanglard return CddlType::Op::kInclusiveRange;
208*3f982cf4SFabien Sanglard } else if (rangeop.text == "...") {
209*3f982cf4SFabien Sanglard return CddlType::Op::kExclusiveRange;
210*3f982cf4SFabien Sanglard } else {
211*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Unsupported '%s' range operator.\n",
212*3f982cf4SFabien Sanglard rangeop.text.c_str());
213*3f982cf4SFabien Sanglard return CddlType::Op::kNone;
214*3f982cf4SFabien Sanglard }
215*3f982cf4SFabien Sanglard }
216*3f982cf4SFabien Sanglard
AnalyzeCtlop(const AstNode & ctlop)217*3f982cf4SFabien Sanglard CddlType::Op AnalyzeCtlop(const AstNode& ctlop) {
218*3f982cf4SFabien Sanglard if (!ctlop.children) {
219*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Missing id for control operator '%s'.\n",
220*3f982cf4SFabien Sanglard ctlop.text.c_str());
221*3f982cf4SFabien Sanglard return CddlType::Op::kNone;
222*3f982cf4SFabien Sanglard }
223*3f982cf4SFabien Sanglard const std::string& id = ctlop.children->text;
224*3f982cf4SFabien Sanglard if (id == "size") {
225*3f982cf4SFabien Sanglard return CddlType::Op::kSize;
226*3f982cf4SFabien Sanglard } else if (id == "bits") {
227*3f982cf4SFabien Sanglard return CddlType::Op::kBits;
228*3f982cf4SFabien Sanglard } else if (id == "regexp") {
229*3f982cf4SFabien Sanglard return CddlType::Op::kRegexp;
230*3f982cf4SFabien Sanglard } else if (id == "cbor") {
231*3f982cf4SFabien Sanglard return CddlType::Op::kCbor;
232*3f982cf4SFabien Sanglard } else if (id == "cborseq") {
233*3f982cf4SFabien Sanglard return CddlType::Op::kCborseq;
234*3f982cf4SFabien Sanglard } else if (id == "within") {
235*3f982cf4SFabien Sanglard return CddlType::Op::kWithin;
236*3f982cf4SFabien Sanglard } else if (id == "and") {
237*3f982cf4SFabien Sanglard return CddlType::Op::kAnd;
238*3f982cf4SFabien Sanglard } else if (id == "lt") {
239*3f982cf4SFabien Sanglard return CddlType::Op::kLess;
240*3f982cf4SFabien Sanglard } else if (id == "le") {
241*3f982cf4SFabien Sanglard return CddlType::Op::kLessOrEqual;
242*3f982cf4SFabien Sanglard } else if (id == "gt") {
243*3f982cf4SFabien Sanglard return CddlType::Op::kGreater;
244*3f982cf4SFabien Sanglard } else if (id == "ge") {
245*3f982cf4SFabien Sanglard return CddlType::Op::kGreaterOrEqual;
246*3f982cf4SFabien Sanglard } else if (id == "eq") {
247*3f982cf4SFabien Sanglard return CddlType::Op::kEqual;
248*3f982cf4SFabien Sanglard } else if (id == "ne") {
249*3f982cf4SFabien Sanglard return CddlType::Op::kNotEqual;
250*3f982cf4SFabien Sanglard } else if (id == "default") {
251*3f982cf4SFabien Sanglard return CddlType::Op::kDefault;
252*3f982cf4SFabien Sanglard } else {
253*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Unsupported '%s' control operator.\n",
254*3f982cf4SFabien Sanglard ctlop.text.c_str());
255*3f982cf4SFabien Sanglard return CddlType::Op::kNone;
256*3f982cf4SFabien Sanglard }
257*3f982cf4SFabien Sanglard }
258*3f982cf4SFabien Sanglard
259*3f982cf4SFabien Sanglard // Produces CddlType by analyzing AST parsed from type1 rule
260*3f982cf4SFabien Sanglard // ABNF rule: type1 = type2 [S (rangeop / ctlop) S type2]
AnalyzeType1(CddlSymbolTable * table,const AstNode & type1)261*3f982cf4SFabien Sanglard CddlType* AnalyzeType1(CddlSymbolTable* table, const AstNode& type1) {
262*3f982cf4SFabien Sanglard if (!type1.children) {
263*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Missing type2 in type1 '%s'.\n",
264*3f982cf4SFabien Sanglard type1.text.c_str());
265*3f982cf4SFabien Sanglard return nullptr;
266*3f982cf4SFabien Sanglard }
267*3f982cf4SFabien Sanglard const AstNode& target_type = *type1.children;
268*3f982cf4SFabien Sanglard CddlType* analyzed_type = AnalyzeType2(table, target_type);
269*3f982cf4SFabien Sanglard if (!analyzed_type) {
270*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO, "Invalid type2 '%s' in type1 '%s'.\n",
271*3f982cf4SFabien Sanglard target_type.text.c_str(), type1.text.c_str());
272*3f982cf4SFabien Sanglard return nullptr;
273*3f982cf4SFabien Sanglard }
274*3f982cf4SFabien Sanglard if (!target_type.sibling) {
275*3f982cf4SFabien Sanglard // No optional range or control operator, return type as-is
276*3f982cf4SFabien Sanglard return analyzed_type;
277*3f982cf4SFabien Sanglard }
278*3f982cf4SFabien Sanglard const AstNode& operator_type = *target_type.sibling;
279*3f982cf4SFabien Sanglard CddlType::Op op;
280*3f982cf4SFabien Sanglard if (operator_type.type == AstNode::Type::kRangeop) {
281*3f982cf4SFabien Sanglard op = AnalyzeRangeop(operator_type);
282*3f982cf4SFabien Sanglard } else if (operator_type.type == AstNode::Type::kCtlop) {
283*3f982cf4SFabien Sanglard op = AnalyzeCtlop(operator_type);
284*3f982cf4SFabien Sanglard } else {
285*3f982cf4SFabien Sanglard op = CddlType::Op::kNone;
286*3f982cf4SFabien Sanglard }
287*3f982cf4SFabien Sanglard if (op == CddlType::Op::kNone) {
288*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO,
289*3f982cf4SFabien Sanglard "Unsupported or missing operator '%s' in type1 '%s'.\n",
290*3f982cf4SFabien Sanglard operator_type.text.c_str(), type1.text.c_str());
291*3f982cf4SFabien Sanglard return nullptr;
292*3f982cf4SFabien Sanglard }
293*3f982cf4SFabien Sanglard if (!operator_type.sibling) {
294*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO,
295*3f982cf4SFabien Sanglard "Missing controller type for operator '%s' in type1 '%s'.\n",
296*3f982cf4SFabien Sanglard operator_type.text.c_str(), type1.text.c_str());
297*3f982cf4SFabien Sanglard return nullptr;
298*3f982cf4SFabien Sanglard }
299*3f982cf4SFabien Sanglard const AstNode& controller_type = *operator_type.sibling;
300*3f982cf4SFabien Sanglard CddlType* constraint_type = AnalyzeType2(table, controller_type);
301*3f982cf4SFabien Sanglard if (!constraint_type) {
302*3f982cf4SFabien Sanglard dprintf(STDERR_FILENO,
303*3f982cf4SFabien Sanglard "Invalid controller type '%s' for operator '%s' in type1 '%s'.\n",
304*3f982cf4SFabien Sanglard controller_type.text.c_str(), operator_type.text.c_str(),
305*3f982cf4SFabien Sanglard type1.text.c_str());
306*3f982cf4SFabien Sanglard return nullptr;
307*3f982cf4SFabien Sanglard }
308*3f982cf4SFabien Sanglard analyzed_type->op = op;
309*3f982cf4SFabien Sanglard analyzed_type->constraint_type = constraint_type;
310*3f982cf4SFabien Sanglard return analyzed_type;
311*3f982cf4SFabien Sanglard }
312*3f982cf4SFabien Sanglard
AnalyzeType(CddlSymbolTable * table,const AstNode & type)313*3f982cf4SFabien Sanglard CddlType* AnalyzeType(CddlSymbolTable* table, const AstNode& type) {
314*3f982cf4SFabien Sanglard const AstNode* type1 = type.children;
315*3f982cf4SFabien Sanglard if (type1->sibling) {
316*3f982cf4SFabien Sanglard // If the type we are looking at has a type choice, create a top-level
317*3f982cf4SFabien Sanglard // choice object, with a vector containing all valid choices.
318*3f982cf4SFabien Sanglard CddlType* type_choice = AddCddlType(table, CddlType::Which::kDirectChoice);
319*3f982cf4SFabien Sanglard InitDirectChoice(&type_choice->direct_choice);
320*3f982cf4SFabien Sanglard while (type1) {
321*3f982cf4SFabien Sanglard type_choice->direct_choice.push_back(AnalyzeType1(table, *type1));
322*3f982cf4SFabien Sanglard type1 = type1->sibling;
323*3f982cf4SFabien Sanglard }
324*3f982cf4SFabien Sanglard return type_choice;
325*3f982cf4SFabien Sanglard } else {
326*3f982cf4SFabien Sanglard // Else just return the single choice.
327*3f982cf4SFabien Sanglard return AnalyzeType1(table, *type1);
328*3f982cf4SFabien Sanglard }
329*3f982cf4SFabien Sanglard }
330*3f982cf4SFabien Sanglard
331*3f982cf4SFabien Sanglard bool AnalyzeGroupEntry(CddlSymbolTable* table,
332*3f982cf4SFabien Sanglard const AstNode& group_entry,
333*3f982cf4SFabien Sanglard CddlGroup::Entry* entry);
334*3f982cf4SFabien Sanglard
AnalyzeGroup(CddlSymbolTable * table,const AstNode & group)335*3f982cf4SFabien Sanglard CddlGroup* AnalyzeGroup(CddlSymbolTable* table, const AstNode& group) {
336*3f982cf4SFabien Sanglard // NOTE: |group.children| is a grpchoice, which we don't currently handle.
337*3f982cf4SFabien Sanglard // Therefore, we assume it has no siblings and move on to immediately handling
338*3f982cf4SFabien Sanglard // its grpent children.
339*3f982cf4SFabien Sanglard const AstNode* node = group.children->children;
340*3f982cf4SFabien Sanglard table->groups.emplace_back(new CddlGroup);
341*3f982cf4SFabien Sanglard CddlGroup* group_def = table->groups.back().get();
342*3f982cf4SFabien Sanglard while (node) {
343*3f982cf4SFabien Sanglard group_def->entries.emplace_back(new CddlGroup::Entry);
344*3f982cf4SFabien Sanglard AnalyzeGroupEntry(table, *node, group_def->entries.back().get());
345*3f982cf4SFabien Sanglard node = node->sibling;
346*3f982cf4SFabien Sanglard }
347*3f982cf4SFabien Sanglard return group_def;
348*3f982cf4SFabien Sanglard }
349*3f982cf4SFabien Sanglard
350*3f982cf4SFabien Sanglard // Parses a string into an optional uint64_t, with the value being that
351*3f982cf4SFabien Sanglard // represented by the string if it is present and nullopt if it cannot
352*3f982cf4SFabien Sanglard // be parsed.
353*3f982cf4SFabien Sanglard // TODO(rwkeane): Add support for hex and binary options.
ParseOptionalUint(const std::string & text)354*3f982cf4SFabien Sanglard absl::optional<uint64_t> ParseOptionalUint(const std::string& text) {
355*3f982cf4SFabien Sanglard if (text == "0") {
356*3f982cf4SFabien Sanglard return 0;
357*3f982cf4SFabien Sanglard }
358*3f982cf4SFabien Sanglard
359*3f982cf4SFabien Sanglard uint64_t parsed = std::strtoul(text.c_str(), nullptr, 10);
360*3f982cf4SFabien Sanglard if (!parsed) {
361*3f982cf4SFabien Sanglard return absl::nullopt;
362*3f982cf4SFabien Sanglard }
363*3f982cf4SFabien Sanglard return parsed;
364*3f982cf4SFabien Sanglard }
365*3f982cf4SFabien Sanglard
AnalyzeGroupEntry(CddlSymbolTable * table,const AstNode & group_entry,CddlGroup::Entry * entry)366*3f982cf4SFabien Sanglard bool AnalyzeGroupEntry(CddlSymbolTable* table,
367*3f982cf4SFabien Sanglard const AstNode& group_entry,
368*3f982cf4SFabien Sanglard CddlGroup::Entry* entry) {
369*3f982cf4SFabien Sanglard const AstNode* node = group_entry.children;
370*3f982cf4SFabien Sanglard
371*3f982cf4SFabien Sanglard // If it's an occurance operator (so the entry is optional), mark it as such
372*3f982cf4SFabien Sanglard // and proceed to the next the node.
373*3f982cf4SFabien Sanglard if (node->type == AstNode::Type::kOccur) {
374*3f982cf4SFabien Sanglard if (node->text == "?") {
375*3f982cf4SFabien Sanglard entry->opt_occurrence_min = CddlGroup::Entry::kOccurrenceMinUnbounded;
376*3f982cf4SFabien Sanglard entry->opt_occurrence_max = 1;
377*3f982cf4SFabien Sanglard } else if (node->text == "+") {
378*3f982cf4SFabien Sanglard entry->opt_occurrence_min = 1;
379*3f982cf4SFabien Sanglard entry->opt_occurrence_max = CddlGroup::Entry::kOccurrenceMaxUnbounded;
380*3f982cf4SFabien Sanglard } else {
381*3f982cf4SFabien Sanglard auto index = node->text.find('*');
382*3f982cf4SFabien Sanglard if (index == std::string::npos) {
383*3f982cf4SFabien Sanglard return false;
384*3f982cf4SFabien Sanglard }
385*3f982cf4SFabien Sanglard
386*3f982cf4SFabien Sanglard int lower_bound = CddlGroup::Entry::kOccurrenceMinUnbounded;
387*3f982cf4SFabien Sanglard std::string first_half = node->text.substr(0, index);
388*3f982cf4SFabien Sanglard if ((first_half.length() != 1 || first_half.at(0) != '0') &&
389*3f982cf4SFabien Sanglard first_half.length() != 0) {
390*3f982cf4SFabien Sanglard lower_bound = std::atoi(first_half.c_str());
391*3f982cf4SFabien Sanglard if (!lower_bound) {
392*3f982cf4SFabien Sanglard return false;
393*3f982cf4SFabien Sanglard }
394*3f982cf4SFabien Sanglard }
395*3f982cf4SFabien Sanglard
396*3f982cf4SFabien Sanglard int upper_bound = CddlGroup::Entry::kOccurrenceMaxUnbounded;
397*3f982cf4SFabien Sanglard std::string second_half =
398*3f982cf4SFabien Sanglard index >= node->text.length() ? "" : node->text.substr(index + 1);
399*3f982cf4SFabien Sanglard if ((second_half.length() != 1 || second_half.at(0) != '0') &&
400*3f982cf4SFabien Sanglard second_half.length() != 0) {
401*3f982cf4SFabien Sanglard upper_bound = std::atoi(second_half.c_str());
402*3f982cf4SFabien Sanglard if (!upper_bound) {
403*3f982cf4SFabien Sanglard return false;
404*3f982cf4SFabien Sanglard }
405*3f982cf4SFabien Sanglard }
406*3f982cf4SFabien Sanglard
407*3f982cf4SFabien Sanglard entry->opt_occurrence_min = lower_bound;
408*3f982cf4SFabien Sanglard entry->opt_occurrence_max = upper_bound;
409*3f982cf4SFabien Sanglard }
410*3f982cf4SFabien Sanglard entry->occurrence_specified = true;
411*3f982cf4SFabien Sanglard node = node->sibling;
412*3f982cf4SFabien Sanglard } else {
413*3f982cf4SFabien Sanglard entry->opt_occurrence_min = 1;
414*3f982cf4SFabien Sanglard entry->opt_occurrence_max = 1;
415*3f982cf4SFabien Sanglard entry->occurrence_specified = false;
416*3f982cf4SFabien Sanglard }
417*3f982cf4SFabien Sanglard
418*3f982cf4SFabien Sanglard // If it's a member key (key in a map), save it and go to next node.
419*3f982cf4SFabien Sanglard if (node->type == AstNode::Type::kMemberKey) {
420*3f982cf4SFabien Sanglard if (node->text[node->text.size() - 1] == '>')
421*3f982cf4SFabien Sanglard return false;
422*3f982cf4SFabien Sanglard entry->which = CddlGroup::Entry::Which::kType;
423*3f982cf4SFabien Sanglard InitGroupEntry(&entry->type);
424*3f982cf4SFabien Sanglard entry->type.opt_key = std::string(node->children->text);
425*3f982cf4SFabien Sanglard entry->type.integer_key = ParseOptionalUint(node->integer_member_key_text);
426*3f982cf4SFabien Sanglard node = node->sibling;
427*3f982cf4SFabien Sanglard }
428*3f982cf4SFabien Sanglard
429*3f982cf4SFabien Sanglard // If it's a type, process it as such.
430*3f982cf4SFabien Sanglard if (node->type == AstNode::Type::kType) {
431*3f982cf4SFabien Sanglard if (entry->which == CddlGroup::Entry::Which::kUninitialized) {
432*3f982cf4SFabien Sanglard entry->which = CddlGroup::Entry::Which::kType;
433*3f982cf4SFabien Sanglard InitGroupEntry(&entry->type);
434*3f982cf4SFabien Sanglard }
435*3f982cf4SFabien Sanglard entry->type.value = AnalyzeType(table, *node);
436*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kGroupname) {
437*3f982cf4SFabien Sanglard return false;
438*3f982cf4SFabien Sanglard } else if (node->type == AstNode::Type::kGroup) {
439*3f982cf4SFabien Sanglard entry->which = CddlGroup::Entry::Which::kGroup;
440*3f982cf4SFabien Sanglard entry->group = AnalyzeGroup(table, *node);
441*3f982cf4SFabien Sanglard }
442*3f982cf4SFabien Sanglard return true;
443*3f982cf4SFabien Sanglard }
444*3f982cf4SFabien Sanglard
BuildSymbolTable(const AstNode & rules)445*3f982cf4SFabien Sanglard std::pair<bool, CddlSymbolTable> BuildSymbolTable(const AstNode& rules) {
446*3f982cf4SFabien Sanglard std::pair<bool, CddlSymbolTable> result;
447*3f982cf4SFabien Sanglard result.first = false;
448*3f982cf4SFabien Sanglard auto& table = result.second;
449*3f982cf4SFabien Sanglard
450*3f982cf4SFabien Sanglard // Parse over all rules iteratively.
451*3f982cf4SFabien Sanglard for (const AstNode* rule = &rules; rule; rule = rule->sibling) {
452*3f982cf4SFabien Sanglard AstNode* node = rule->children;
453*3f982cf4SFabien Sanglard
454*3f982cf4SFabien Sanglard // Ensure that the node is either a type or group definition.
455*3f982cf4SFabien Sanglard if (node->type != AstNode::Type::kTypename &&
456*3f982cf4SFabien Sanglard node->type != AstNode::Type::kGroupname) {
457*3f982cf4SFabien Sanglard Logger::Error("Error parsing node with text '%s'. Unexpected node type.",
458*3f982cf4SFabien Sanglard node->text);
459*3f982cf4SFabien Sanglard return result;
460*3f982cf4SFabien Sanglard }
461*3f982cf4SFabien Sanglard bool is_type = node->type == AstNode::Type::kTypename;
462*3f982cf4SFabien Sanglard absl::string_view name = node->text;
463*3f982cf4SFabien Sanglard
464*3f982cf4SFabien Sanglard // Ensure that the node is assignment.
465*3f982cf4SFabien Sanglard node = node->sibling;
466*3f982cf4SFabien Sanglard if (node->type != AstNode::Type::kAssign) {
467*3f982cf4SFabien Sanglard Logger::Error("Error parsing node with text '%s'. Node type != kAssign.",
468*3f982cf4SFabien Sanglard node->text);
469*3f982cf4SFabien Sanglard return result;
470*3f982cf4SFabien Sanglard }
471*3f982cf4SFabien Sanglard
472*3f982cf4SFabien Sanglard // Process the definition.
473*3f982cf4SFabien Sanglard node = node->sibling;
474*3f982cf4SFabien Sanglard if (is_type) {
475*3f982cf4SFabien Sanglard CddlType* type = AnalyzeType(&table, *node);
476*3f982cf4SFabien Sanglard if (rule->type_key != absl::nullopt) {
477*3f982cf4SFabien Sanglard auto parsed_type_key = ParseOptionalUint(rule->type_key.value());
478*3f982cf4SFabien Sanglard if (parsed_type_key == absl::nullopt) {
479*3f982cf4SFabien Sanglard return result;
480*3f982cf4SFabien Sanglard }
481*3f982cf4SFabien Sanglard type->type_key = parsed_type_key.value();
482*3f982cf4SFabien Sanglard }
483*3f982cf4SFabien Sanglard if (!type) {
484*3f982cf4SFabien Sanglard Logger::Error(
485*3f982cf4SFabien Sanglard "Error parsing node with text '%s'."
486*3f982cf4SFabien Sanglard "Failed to analyze node type.",
487*3f982cf4SFabien Sanglard node->text);
488*3f982cf4SFabien Sanglard }
489*3f982cf4SFabien Sanglard table.type_map.emplace(std::string(name), type);
490*3f982cf4SFabien Sanglard } else {
491*3f982cf4SFabien Sanglard table.groups.emplace_back(new CddlGroup);
492*3f982cf4SFabien Sanglard CddlGroup* group = table.groups.back().get();
493*3f982cf4SFabien Sanglard group->entries.emplace_back(new CddlGroup::Entry);
494*3f982cf4SFabien Sanglard AnalyzeGroupEntry(&table, *node, group->entries.back().get());
495*3f982cf4SFabien Sanglard table.group_map.emplace(std::string(name), group);
496*3f982cf4SFabien Sanglard }
497*3f982cf4SFabien Sanglard }
498*3f982cf4SFabien Sanglard
499*3f982cf4SFabien Sanglard DumpSymbolTable(&result.second);
500*3f982cf4SFabien Sanglard
501*3f982cf4SFabien Sanglard result.first = true;
502*3f982cf4SFabien Sanglard return result;
503*3f982cf4SFabien Sanglard }
504*3f982cf4SFabien Sanglard
505*3f982cf4SFabien Sanglard // Fetches a C++ Type from all known definitons, or inserts a placeholder to be
506*3f982cf4SFabien Sanglard // updated later if the type hasn't been defined yet.
GetCppType(CppSymbolTable * table,const std::string & name)507*3f982cf4SFabien Sanglard CppType* GetCppType(CppSymbolTable* table, const std::string& name) {
508*3f982cf4SFabien Sanglard if (name.empty()) {
509*3f982cf4SFabien Sanglard table->cpp_types.emplace_back(new CppType);
510*3f982cf4SFabien Sanglard return table->cpp_types.back().get();
511*3f982cf4SFabien Sanglard }
512*3f982cf4SFabien Sanglard auto entry = table->cpp_type_map.find(name);
513*3f982cf4SFabien Sanglard if (entry != table->cpp_type_map.end())
514*3f982cf4SFabien Sanglard return entry->second;
515*3f982cf4SFabien Sanglard table->cpp_types.emplace_back(new CppType);
516*3f982cf4SFabien Sanglard table->cpp_type_map.emplace(name, table->cpp_types.back().get());
517*3f982cf4SFabien Sanglard return table->cpp_types.back().get();
518*3f982cf4SFabien Sanglard }
519*3f982cf4SFabien Sanglard
520*3f982cf4SFabien Sanglard bool IncludeGroupMembersInEnum(CppSymbolTable* table,
521*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
522*3f982cf4SFabien Sanglard CppType* cpp_type,
523*3f982cf4SFabien Sanglard const CddlGroup& group);
524*3f982cf4SFabien Sanglard
IncludeGroupMembersInSubEnum(CppSymbolTable * table,const CddlSymbolTable & cddl_table,CppType * cpp_type,const std::string & name)525*3f982cf4SFabien Sanglard bool IncludeGroupMembersInSubEnum(CppSymbolTable* table,
526*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
527*3f982cf4SFabien Sanglard CppType* cpp_type,
528*3f982cf4SFabien Sanglard const std::string& name) {
529*3f982cf4SFabien Sanglard auto group_entry = cddl_table.group_map.find(name);
530*3f982cf4SFabien Sanglard if (group_entry == cddl_table.group_map.end()) {
531*3f982cf4SFabien Sanglard return false;
532*3f982cf4SFabien Sanglard }
533*3f982cf4SFabien Sanglard if (group_entry->second->entries.size() != 1 ||
534*3f982cf4SFabien Sanglard group_entry->second->entries[0]->which !=
535*3f982cf4SFabien Sanglard CddlGroup::Entry::Which::kGroup) {
536*3f982cf4SFabien Sanglard return false;
537*3f982cf4SFabien Sanglard }
538*3f982cf4SFabien Sanglard CppType* sub_enum = GetCppType(table, name);
539*3f982cf4SFabien Sanglard if (sub_enum->which == CppType::Which::kUninitialized) {
540*3f982cf4SFabien Sanglard sub_enum->InitEnum();
541*3f982cf4SFabien Sanglard sub_enum->name = name;
542*3f982cf4SFabien Sanglard if (!IncludeGroupMembersInEnum(table, cddl_table, sub_enum,
543*3f982cf4SFabien Sanglard *group_entry->second->entries[0]->group)) {
544*3f982cf4SFabien Sanglard return false;
545*3f982cf4SFabien Sanglard }
546*3f982cf4SFabien Sanglard }
547*3f982cf4SFabien Sanglard cpp_type->enum_type.sub_members.push_back(sub_enum);
548*3f982cf4SFabien Sanglard return true;
549*3f982cf4SFabien Sanglard }
550*3f982cf4SFabien Sanglard
IncludeGroupMembersInEnum(CppSymbolTable * table,const CddlSymbolTable & cddl_table,CppType * cpp_type,const CddlGroup & group)551*3f982cf4SFabien Sanglard bool IncludeGroupMembersInEnum(CppSymbolTable* table,
552*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
553*3f982cf4SFabien Sanglard CppType* cpp_type,
554*3f982cf4SFabien Sanglard const CddlGroup& group) {
555*3f982cf4SFabien Sanglard for (const auto& x : group.entries) {
556*3f982cf4SFabien Sanglard if (x->HasOccurrenceOperator() ||
557*3f982cf4SFabien Sanglard x->which != CddlGroup::Entry::Which::kType) {
558*3f982cf4SFabien Sanglard return false;
559*3f982cf4SFabien Sanglard }
560*3f982cf4SFabien Sanglard if (x->type.value->which == CddlType::Which::kValue &&
561*3f982cf4SFabien Sanglard !x->type.opt_key.empty()) {
562*3f982cf4SFabien Sanglard cpp_type->enum_type.members.emplace_back(
563*3f982cf4SFabien Sanglard x->type.opt_key, atoi(x->type.value->value.c_str()));
564*3f982cf4SFabien Sanglard } else if (x->type.value->which == CddlType::Which::kId) {
565*3f982cf4SFabien Sanglard IncludeGroupMembersInSubEnum(table, cddl_table, cpp_type,
566*3f982cf4SFabien Sanglard x->type.value->id);
567*3f982cf4SFabien Sanglard } else {
568*3f982cf4SFabien Sanglard return false;
569*3f982cf4SFabien Sanglard }
570*3f982cf4SFabien Sanglard }
571*3f982cf4SFabien Sanglard return true;
572*3f982cf4SFabien Sanglard }
573*3f982cf4SFabien Sanglard
574*3f982cf4SFabien Sanglard CppType* MakeCppType(CppSymbolTable* table,
575*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
576*3f982cf4SFabien Sanglard const std::string& name,
577*3f982cf4SFabien Sanglard const CddlType& type);
578*3f982cf4SFabien Sanglard
AddMembersToStruct(CppSymbolTable * table,const CddlSymbolTable & cddl_table,CppType * cpp_type,const std::vector<std::unique_ptr<CddlGroup::Entry>> & entries)579*3f982cf4SFabien Sanglard bool AddMembersToStruct(
580*3f982cf4SFabien Sanglard CppSymbolTable* table,
581*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
582*3f982cf4SFabien Sanglard CppType* cpp_type,
583*3f982cf4SFabien Sanglard const std::vector<std::unique_ptr<CddlGroup::Entry>>& entries) {
584*3f982cf4SFabien Sanglard for (const auto& x : entries) {
585*3f982cf4SFabien Sanglard if (x->which == CddlGroup::Entry::Which::kType) {
586*3f982cf4SFabien Sanglard if (x->type.opt_key.empty()) {
587*3f982cf4SFabien Sanglard // If the represented node has no text (ie - it's code generated) then
588*3f982cf4SFabien Sanglard // it must have an inner type that is based on the user input. If this
589*3f982cf4SFabien Sanglard // one looks as expected, process it recursively.
590*3f982cf4SFabien Sanglard if (x->type.value->which != CddlType::Which::kId ||
591*3f982cf4SFabien Sanglard x->HasOccurrenceOperator()) {
592*3f982cf4SFabien Sanglard return false;
593*3f982cf4SFabien Sanglard }
594*3f982cf4SFabien Sanglard auto group_entry = cddl_table.group_map.find(x->type.value->id);
595*3f982cf4SFabien Sanglard if (group_entry == cddl_table.group_map.end())
596*3f982cf4SFabien Sanglard return false;
597*3f982cf4SFabien Sanglard if (group_entry->second->entries.size() != 1 ||
598*3f982cf4SFabien Sanglard group_entry->second->entries[0]->which !=
599*3f982cf4SFabien Sanglard CddlGroup::Entry::Which::kGroup) {
600*3f982cf4SFabien Sanglard return false;
601*3f982cf4SFabien Sanglard }
602*3f982cf4SFabien Sanglard if (!AddMembersToStruct(
603*3f982cf4SFabien Sanglard table, cddl_table, cpp_type,
604*3f982cf4SFabien Sanglard group_entry->second->entries[0]->group->entries)) {
605*3f982cf4SFabien Sanglard return false;
606*3f982cf4SFabien Sanglard }
607*3f982cf4SFabien Sanglard } else {
608*3f982cf4SFabien Sanglard // Here it is a real type definition - so process it as such.
609*3f982cf4SFabien Sanglard CppType* member_type =
610*3f982cf4SFabien Sanglard MakeCppType(table, cddl_table,
611*3f982cf4SFabien Sanglard cpp_type->name + std::string("_") + x->type.opt_key,
612*3f982cf4SFabien Sanglard *x->type.value);
613*3f982cf4SFabien Sanglard if (!member_type)
614*3f982cf4SFabien Sanglard return false;
615*3f982cf4SFabien Sanglard if (member_type->name.empty())
616*3f982cf4SFabien Sanglard member_type->name = x->type.opt_key;
617*3f982cf4SFabien Sanglard if (x->opt_occurrence_min ==
618*3f982cf4SFabien Sanglard CddlGroup::Entry::kOccurrenceMinUnbounded &&
619*3f982cf4SFabien Sanglard x->opt_occurrence_max == 1) {
620*3f982cf4SFabien Sanglard // Create an "optional" type, with sub-type being the type that is
621*3f982cf4SFabien Sanglard // optional. This corresponds with occurrence operator '?'.
622*3f982cf4SFabien Sanglard table->cpp_types.emplace_back(new CppType);
623*3f982cf4SFabien Sanglard CppType* optional_type = table->cpp_types.back().get();
624*3f982cf4SFabien Sanglard optional_type->which = CppType::Which::kOptional;
625*3f982cf4SFabien Sanglard optional_type->optional_type = member_type;
626*3f982cf4SFabien Sanglard cpp_type->struct_type.members.emplace_back(
627*3f982cf4SFabien Sanglard x->type.opt_key, x->type.integer_key, optional_type);
628*3f982cf4SFabien Sanglard } else {
629*3f982cf4SFabien Sanglard cpp_type->struct_type.members.emplace_back(
630*3f982cf4SFabien Sanglard x->type.opt_key, x->type.integer_key, member_type);
631*3f982cf4SFabien Sanglard }
632*3f982cf4SFabien Sanglard }
633*3f982cf4SFabien Sanglard } else {
634*3f982cf4SFabien Sanglard // If it's not a type, it's a group so add its members recursuvely.
635*3f982cf4SFabien Sanglard if (!AddMembersToStruct(table, cddl_table, cpp_type, x->group->entries))
636*3f982cf4SFabien Sanglard return false;
637*3f982cf4SFabien Sanglard }
638*3f982cf4SFabien Sanglard }
639*3f982cf4SFabien Sanglard return true;
640*3f982cf4SFabien Sanglard }
641*3f982cf4SFabien Sanglard
MakeCppType(CppSymbolTable * table,const CddlSymbolTable & cddl_table,const std::string & name,const CddlType & type)642*3f982cf4SFabien Sanglard CppType* MakeCppType(CppSymbolTable* table,
643*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table,
644*3f982cf4SFabien Sanglard const std::string& name,
645*3f982cf4SFabien Sanglard const CddlType& type) {
646*3f982cf4SFabien Sanglard CppType* cpp_type = nullptr;
647*3f982cf4SFabien Sanglard switch (type.which) {
648*3f982cf4SFabien Sanglard case CddlType::Which::kId: {
649*3f982cf4SFabien Sanglard if (type.id == "uint") {
650*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
651*3f982cf4SFabien Sanglard cpp_type->which = CppType::Which::kUint64;
652*3f982cf4SFabien Sanglard } else if (type.id == "text") {
653*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
654*3f982cf4SFabien Sanglard cpp_type->which = CppType::Which::kString;
655*3f982cf4SFabien Sanglard } else if (type.id == "bytes") {
656*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
657*3f982cf4SFabien Sanglard cpp_type->InitBytes();
658*3f982cf4SFabien Sanglard if (type.op == CddlType::Op::kSize) {
659*3f982cf4SFabien Sanglard size_t size = 0;
660*3f982cf4SFabien Sanglard if (!absl::SimpleAtoi(type.constraint_type->value, &size)) {
661*3f982cf4SFabien Sanglard return nullptr;
662*3f982cf4SFabien Sanglard }
663*3f982cf4SFabien Sanglard cpp_type->bytes_type.fixed_size = size;
664*3f982cf4SFabien Sanglard }
665*3f982cf4SFabien Sanglard } else {
666*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, type.id);
667*3f982cf4SFabien Sanglard }
668*3f982cf4SFabien Sanglard } break;
669*3f982cf4SFabien Sanglard case CddlType::Which::kMap: {
670*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
671*3f982cf4SFabien Sanglard cpp_type->InitStruct();
672*3f982cf4SFabien Sanglard cpp_type->struct_type.key_type = CppType::Struct::KeyType::kMap;
673*3f982cf4SFabien Sanglard cpp_type->name = name;
674*3f982cf4SFabien Sanglard if (!AddMembersToStruct(table, cddl_table, cpp_type, type.map->entries))
675*3f982cf4SFabien Sanglard return nullptr;
676*3f982cf4SFabien Sanglard } break;
677*3f982cf4SFabien Sanglard case CddlType::Which::kArray: {
678*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
679*3f982cf4SFabien Sanglard if (type.array->entries.size() == 1 &&
680*3f982cf4SFabien Sanglard type.array->entries[0]->HasOccurrenceOperator()) {
681*3f982cf4SFabien Sanglard cpp_type->InitVector();
682*3f982cf4SFabien Sanglard cpp_type->vector_type.min_length =
683*3f982cf4SFabien Sanglard type.array->entries[0]->opt_occurrence_min;
684*3f982cf4SFabien Sanglard cpp_type->vector_type.max_length =
685*3f982cf4SFabien Sanglard type.array->entries[0]->opt_occurrence_max;
686*3f982cf4SFabien Sanglard cpp_type->vector_type.element_type =
687*3f982cf4SFabien Sanglard GetCppType(table, type.array->entries[0]->type.value->id);
688*3f982cf4SFabien Sanglard } else {
689*3f982cf4SFabien Sanglard cpp_type->InitStruct();
690*3f982cf4SFabien Sanglard cpp_type->struct_type.key_type = CppType::Struct::KeyType::kArray;
691*3f982cf4SFabien Sanglard cpp_type->name = name;
692*3f982cf4SFabien Sanglard if (!AddMembersToStruct(table, cddl_table, cpp_type,
693*3f982cf4SFabien Sanglard type.map->entries)) {
694*3f982cf4SFabien Sanglard return nullptr;
695*3f982cf4SFabien Sanglard }
696*3f982cf4SFabien Sanglard }
697*3f982cf4SFabien Sanglard } break;
698*3f982cf4SFabien Sanglard case CddlType::Which::kGroupChoice: {
699*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
700*3f982cf4SFabien Sanglard cpp_type->InitEnum();
701*3f982cf4SFabien Sanglard cpp_type->name = name;
702*3f982cf4SFabien Sanglard if (!IncludeGroupMembersInEnum(table, cddl_table, cpp_type,
703*3f982cf4SFabien Sanglard *type.group_choice)) {
704*3f982cf4SFabien Sanglard return nullptr;
705*3f982cf4SFabien Sanglard }
706*3f982cf4SFabien Sanglard } break;
707*3f982cf4SFabien Sanglard case CddlType::Which::kGroupnameChoice: {
708*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
709*3f982cf4SFabien Sanglard cpp_type->InitEnum();
710*3f982cf4SFabien Sanglard cpp_type->name = name;
711*3f982cf4SFabien Sanglard if (!IncludeGroupMembersInSubEnum(table, cddl_table, cpp_type, type.id)) {
712*3f982cf4SFabien Sanglard return nullptr;
713*3f982cf4SFabien Sanglard }
714*3f982cf4SFabien Sanglard } break;
715*3f982cf4SFabien Sanglard case CddlType::Which::kDirectChoice: {
716*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
717*3f982cf4SFabien Sanglard cpp_type->InitDiscriminatedUnion();
718*3f982cf4SFabien Sanglard for (const auto* cddl_choice : type.direct_choice) {
719*3f982cf4SFabien Sanglard CppType* member = MakeCppType(table, cddl_table, "", *cddl_choice);
720*3f982cf4SFabien Sanglard if (!member)
721*3f982cf4SFabien Sanglard return nullptr;
722*3f982cf4SFabien Sanglard cpp_type->discriminated_union.members.push_back(member);
723*3f982cf4SFabien Sanglard }
724*3f982cf4SFabien Sanglard return cpp_type;
725*3f982cf4SFabien Sanglard }
726*3f982cf4SFabien Sanglard case CddlType::Which::kTaggedType: {
727*3f982cf4SFabien Sanglard cpp_type = GetCppType(table, name);
728*3f982cf4SFabien Sanglard cpp_type->which = CppType::Which::kTaggedType;
729*3f982cf4SFabien Sanglard cpp_type->tagged_type.tag = type.tagged_type.tag_value;
730*3f982cf4SFabien Sanglard cpp_type->tagged_type.real_type =
731*3f982cf4SFabien Sanglard MakeCppType(table, cddl_table, "", *type.tagged_type.type);
732*3f982cf4SFabien Sanglard } break;
733*3f982cf4SFabien Sanglard default:
734*3f982cf4SFabien Sanglard return nullptr;
735*3f982cf4SFabien Sanglard }
736*3f982cf4SFabien Sanglard
737*3f982cf4SFabien Sanglard cpp_type->type_key = type.type_key;
738*3f982cf4SFabien Sanglard return cpp_type;
739*3f982cf4SFabien Sanglard }
740*3f982cf4SFabien Sanglard
PrePopulateCppTypes(CppSymbolTable * table)741*3f982cf4SFabien Sanglard void PrePopulateCppTypes(CppSymbolTable* table) {
742*3f982cf4SFabien Sanglard std::vector<std::pair<std::string, CppType::Which>> default_types;
743*3f982cf4SFabien Sanglard default_types.emplace_back("text", CppType::Which::kString);
744*3f982cf4SFabien Sanglard default_types.emplace_back("tstr", CppType::Which::kString);
745*3f982cf4SFabien Sanglard default_types.emplace_back("bstr", CppType::Which::kBytes);
746*3f982cf4SFabien Sanglard default_types.emplace_back("bytes", CppType::Which::kBytes);
747*3f982cf4SFabien Sanglard default_types.emplace_back("uint", CppType::Which::kUint64);
748*3f982cf4SFabien Sanglard
749*3f982cf4SFabien Sanglard for (auto& pair : default_types) {
750*3f982cf4SFabien Sanglard auto entry = table->cpp_type_map.find(pair.first);
751*3f982cf4SFabien Sanglard if (entry != table->cpp_type_map.end())
752*3f982cf4SFabien Sanglard continue;
753*3f982cf4SFabien Sanglard table->cpp_types.emplace_back(new CppType);
754*3f982cf4SFabien Sanglard auto* type = table->cpp_types.back().get();
755*3f982cf4SFabien Sanglard type->name = pair.first;
756*3f982cf4SFabien Sanglard type->which = pair.second;
757*3f982cf4SFabien Sanglard table->cpp_type_map.emplace(pair.first, type);
758*3f982cf4SFabien Sanglard }
759*3f982cf4SFabien Sanglard }
760*3f982cf4SFabien Sanglard
BuildCppTypes(const CddlSymbolTable & cddl_table)761*3f982cf4SFabien Sanglard std::pair<bool, CppSymbolTable> BuildCppTypes(
762*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table) {
763*3f982cf4SFabien Sanglard std::pair<bool, CppSymbolTable> result;
764*3f982cf4SFabien Sanglard result.first = false;
765*3f982cf4SFabien Sanglard PrePopulateCppTypes(&result.second);
766*3f982cf4SFabien Sanglard auto& table = result.second;
767*3f982cf4SFabien Sanglard for (const auto& type_entry : cddl_table.type_map) {
768*3f982cf4SFabien Sanglard if (!MakeCppType(&table, cddl_table, type_entry.first,
769*3f982cf4SFabien Sanglard *type_entry.second)) {
770*3f982cf4SFabien Sanglard return result;
771*3f982cf4SFabien Sanglard }
772*3f982cf4SFabien Sanglard }
773*3f982cf4SFabien Sanglard
774*3f982cf4SFabien Sanglard result.first = true;
775*3f982cf4SFabien Sanglard return result;
776*3f982cf4SFabien Sanglard }
777*3f982cf4SFabien Sanglard
VerifyUniqueKeysInMember(std::unordered_set<std::string> * keys,const CppType::Struct::CppMember & member)778*3f982cf4SFabien Sanglard bool VerifyUniqueKeysInMember(std::unordered_set<std::string>* keys,
779*3f982cf4SFabien Sanglard const CppType::Struct::CppMember& member) {
780*3f982cf4SFabien Sanglard return keys->insert(member.name).second &&
781*3f982cf4SFabien Sanglard (!member.integer_key.has_value() ||
782*3f982cf4SFabien Sanglard keys->insert(std::to_string(member.integer_key.value())).second);
783*3f982cf4SFabien Sanglard }
784*3f982cf4SFabien Sanglard
HasUniqueKeys(const CppType & type)785*3f982cf4SFabien Sanglard bool HasUniqueKeys(const CppType& type) {
786*3f982cf4SFabien Sanglard std::unordered_set<std::string> keys;
787*3f982cf4SFabien Sanglard return type.which != CppType::Which::kStruct ||
788*3f982cf4SFabien Sanglard absl::c_all_of(type.struct_type.members,
789*3f982cf4SFabien Sanglard [&keys](const CppType::Struct::CppMember& member) {
790*3f982cf4SFabien Sanglard return VerifyUniqueKeysInMember(&keys, member);
791*3f982cf4SFabien Sanglard });
792*3f982cf4SFabien Sanglard }
793*3f982cf4SFabien Sanglard
IsUniqueEnumValue(std::vector<uint64_t> * values,uint64_t v)794*3f982cf4SFabien Sanglard bool IsUniqueEnumValue(std::vector<uint64_t>* values, uint64_t v) {
795*3f982cf4SFabien Sanglard auto it = std::lower_bound(values->begin(), values->end(), v);
796*3f982cf4SFabien Sanglard if (it == values->end() || *it != v) {
797*3f982cf4SFabien Sanglard values->insert(it, v);
798*3f982cf4SFabien Sanglard return true;
799*3f982cf4SFabien Sanglard }
800*3f982cf4SFabien Sanglard return false;
801*3f982cf4SFabien Sanglard }
802*3f982cf4SFabien Sanglard
HasUniqueEnumValues(std::vector<uint64_t> * values,const CppType & type)803*3f982cf4SFabien Sanglard bool HasUniqueEnumValues(std::vector<uint64_t>* values, const CppType& type) {
804*3f982cf4SFabien Sanglard return absl::c_all_of(type.enum_type.sub_members,
805*3f982cf4SFabien Sanglard [values](CppType* sub_member) {
806*3f982cf4SFabien Sanglard return HasUniqueEnumValues(values, *sub_member);
807*3f982cf4SFabien Sanglard }) &&
808*3f982cf4SFabien Sanglard absl::c_all_of(
809*3f982cf4SFabien Sanglard type.enum_type.members,
810*3f982cf4SFabien Sanglard [values](const std::pair<std::string, uint64_t>& member) {
811*3f982cf4SFabien Sanglard return IsUniqueEnumValue(values, member.second);
812*3f982cf4SFabien Sanglard });
813*3f982cf4SFabien Sanglard }
814*3f982cf4SFabien Sanglard
HasUniqueEnumValues(const CppType & type)815*3f982cf4SFabien Sanglard bool HasUniqueEnumValues(const CppType& type) {
816*3f982cf4SFabien Sanglard std::vector<uint64_t> values;
817*3f982cf4SFabien Sanglard return type.which != CppType::Which::kEnum ||
818*3f982cf4SFabien Sanglard HasUniqueEnumValues(&values, type);
819*3f982cf4SFabien Sanglard }
820*3f982cf4SFabien Sanglard
ValidateCppTypes(const CppSymbolTable & cpp_symbols)821*3f982cf4SFabien Sanglard bool ValidateCppTypes(const CppSymbolTable& cpp_symbols) {
822*3f982cf4SFabien Sanglard return absl::c_all_of(
823*3f982cf4SFabien Sanglard cpp_symbols.cpp_types, [](const std::unique_ptr<CppType>& ptr) {
824*3f982cf4SFabien Sanglard return HasUniqueKeys(*ptr) && HasUniqueEnumValues(*ptr);
825*3f982cf4SFabien Sanglard });
826*3f982cf4SFabien Sanglard }
827*3f982cf4SFabien Sanglard
DumpTypeKey(absl::optional<uint64_t> key)828*3f982cf4SFabien Sanglard std::string DumpTypeKey(absl::optional<uint64_t> key) {
829*3f982cf4SFabien Sanglard if (key != absl::nullopt) {
830*3f982cf4SFabien Sanglard return " (type key=\"" + std::to_string(key.value()) + "\")";
831*3f982cf4SFabien Sanglard }
832*3f982cf4SFabien Sanglard return "";
833*3f982cf4SFabien Sanglard }
834*3f982cf4SFabien Sanglard
DumpType(CddlType * type,int indent_level)835*3f982cf4SFabien Sanglard void DumpType(CddlType* type, int indent_level) {
836*3f982cf4SFabien Sanglard std::string output = "";
837*3f982cf4SFabien Sanglard for (int i = 0; i <= indent_level; ++i)
838*3f982cf4SFabien Sanglard output += "--";
839*3f982cf4SFabien Sanglard switch (type->which) {
840*3f982cf4SFabien Sanglard case CddlType::Which::kDirectChoice:
841*3f982cf4SFabien Sanglard output = "kDirectChoice" + DumpTypeKey(type->type_key) + ": ";
842*3f982cf4SFabien Sanglard Logger::Log(output);
843*3f982cf4SFabien Sanglard for (auto& option : type->direct_choice)
844*3f982cf4SFabien Sanglard DumpType(option, indent_level + 1);
845*3f982cf4SFabien Sanglard break;
846*3f982cf4SFabien Sanglard case CddlType::Which::kValue:
847*3f982cf4SFabien Sanglard output += "kValue" + DumpTypeKey(type->type_key) + ": " + type->value;
848*3f982cf4SFabien Sanglard Logger::Log(output);
849*3f982cf4SFabien Sanglard break;
850*3f982cf4SFabien Sanglard case CddlType::Which::kId:
851*3f982cf4SFabien Sanglard output += "kId" + DumpTypeKey(type->type_key) + ": " + type->id;
852*3f982cf4SFabien Sanglard Logger::Log(output);
853*3f982cf4SFabien Sanglard break;
854*3f982cf4SFabien Sanglard case CddlType::Which::kMap:
855*3f982cf4SFabien Sanglard output += "kMap" + DumpTypeKey(type->type_key) + ": ";
856*3f982cf4SFabien Sanglard Logger::Log(output);
857*3f982cf4SFabien Sanglard DumpGroup(type->map, indent_level + 1);
858*3f982cf4SFabien Sanglard break;
859*3f982cf4SFabien Sanglard case CddlType::Which::kArray:
860*3f982cf4SFabien Sanglard output += "kArray" + DumpTypeKey(type->type_key) + ": ";
861*3f982cf4SFabien Sanglard Logger::Log(output);
862*3f982cf4SFabien Sanglard DumpGroup(type->array, indent_level + 1);
863*3f982cf4SFabien Sanglard break;
864*3f982cf4SFabien Sanglard case CddlType::Which::kGroupChoice:
865*3f982cf4SFabien Sanglard output += "kGroupChoice" + DumpTypeKey(type->type_key) + ": ";
866*3f982cf4SFabien Sanglard Logger::Log(output);
867*3f982cf4SFabien Sanglard DumpGroup(type->group_choice, indent_level + 1);
868*3f982cf4SFabien Sanglard break;
869*3f982cf4SFabien Sanglard case CddlType::Which::kGroupnameChoice:
870*3f982cf4SFabien Sanglard output += "kGroupnameChoice" + DumpTypeKey(type->type_key) + ": ";
871*3f982cf4SFabien Sanglard Logger::Log(output);
872*3f982cf4SFabien Sanglard break;
873*3f982cf4SFabien Sanglard case CddlType::Which::kTaggedType:
874*3f982cf4SFabien Sanglard output += "kTaggedType" + DumpTypeKey(type->type_key) + ": " +
875*3f982cf4SFabien Sanglard std::to_string(type->tagged_type.tag_value);
876*3f982cf4SFabien Sanglard Logger::Log(output);
877*3f982cf4SFabien Sanglard DumpType(type->tagged_type.type, indent_level + 1);
878*3f982cf4SFabien Sanglard break;
879*3f982cf4SFabien Sanglard }
880*3f982cf4SFabien Sanglard }
881*3f982cf4SFabien Sanglard
DumpGroup(CddlGroup * group,int indent_level)882*3f982cf4SFabien Sanglard void DumpGroup(CddlGroup* group, int indent_level) {
883*3f982cf4SFabien Sanglard for (auto& entry : group->entries) {
884*3f982cf4SFabien Sanglard std::string output = "";
885*3f982cf4SFabien Sanglard for (int i = 0; i <= indent_level; ++i)
886*3f982cf4SFabien Sanglard output += "--";
887*3f982cf4SFabien Sanglard switch (entry->which) {
888*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kUninitialized:
889*3f982cf4SFabien Sanglard break;
890*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kType:
891*3f982cf4SFabien Sanglard output += "kType:";
892*3f982cf4SFabien Sanglard if (entry->HasOccurrenceOperator()) {
893*3f982cf4SFabien Sanglard output +=
894*3f982cf4SFabien Sanglard "minOccurance: " + std::to_string(entry->opt_occurrence_min) +
895*3f982cf4SFabien Sanglard " maxOccurance: " + std::to_string(entry->opt_occurrence_max);
896*3f982cf4SFabien Sanglard }
897*3f982cf4SFabien Sanglard if (!entry->type.opt_key.empty()) {
898*3f982cf4SFabien Sanglard output += " " + entry->type.opt_key + "=>";
899*3f982cf4SFabien Sanglard }
900*3f982cf4SFabien Sanglard Logger::Log(output);
901*3f982cf4SFabien Sanglard DumpType(entry->type.value, indent_level + 1);
902*3f982cf4SFabien Sanglard break;
903*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kGroup:
904*3f982cf4SFabien Sanglard if (entry->HasOccurrenceOperator())
905*3f982cf4SFabien Sanglard output +=
906*3f982cf4SFabien Sanglard "minOccurance: " + std::to_string(entry->opt_occurrence_min) +
907*3f982cf4SFabien Sanglard " maxOccurance: " + std::to_string(entry->opt_occurrence_max);
908*3f982cf4SFabien Sanglard Logger::Log(output);
909*3f982cf4SFabien Sanglard DumpGroup(entry->group, indent_level + 1);
910*3f982cf4SFabien Sanglard break;
911*3f982cf4SFabien Sanglard }
912*3f982cf4SFabien Sanglard }
913*3f982cf4SFabien Sanglard }
914*3f982cf4SFabien Sanglard
DumpSymbolTable(CddlSymbolTable * table)915*3f982cf4SFabien Sanglard void DumpSymbolTable(CddlSymbolTable* table) {
916*3f982cf4SFabien Sanglard for (auto& entry : table->type_map) {
917*3f982cf4SFabien Sanglard Logger::Log(entry.first);
918*3f982cf4SFabien Sanglard DumpType(entry.second);
919*3f982cf4SFabien Sanglard }
920*3f982cf4SFabien Sanglard for (auto& entry : table->group_map) {
921*3f982cf4SFabien Sanglard Logger::Log(entry.first);
922*3f982cf4SFabien Sanglard DumpGroup(entry.second);
923*3f982cf4SFabien Sanglard }
924*3f982cf4SFabien Sanglard }
925