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 #ifndef TOOLS_CDDL_SEMA_H_ 6*3f982cf4SFabien Sanglard #define TOOLS_CDDL_SEMA_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard #include <cstdint> 9*3f982cf4SFabien Sanglard #include <iostream> 10*3f982cf4SFabien Sanglard #include <map> 11*3f982cf4SFabien Sanglard #include <memory> 12*3f982cf4SFabien Sanglard #include <string> 13*3f982cf4SFabien Sanglard #include <utility> 14*3f982cf4SFabien Sanglard #include <vector> 15*3f982cf4SFabien Sanglard 16*3f982cf4SFabien Sanglard #include "absl/algorithm/container.h" 17*3f982cf4SFabien Sanglard #include "absl/types/optional.h" 18*3f982cf4SFabien Sanglard #include "tools/cddl/parse.h" 19*3f982cf4SFabien Sanglard 20*3f982cf4SFabien Sanglard struct CddlGroup; 21*3f982cf4SFabien Sanglard 22*3f982cf4SFabien Sanglard // Represents a type defined in CDDL. 23*3f982cf4SFabien Sanglard struct CddlType { 24*3f982cf4SFabien Sanglard // Type of assignment being represented by this CDDL node. 25*3f982cf4SFabien Sanglard enum class Which { 26*3f982cf4SFabien Sanglard kDirectChoice, 27*3f982cf4SFabien Sanglard kValue, 28*3f982cf4SFabien Sanglard kId, 29*3f982cf4SFabien Sanglard kMap, 30*3f982cf4SFabien Sanglard kArray, 31*3f982cf4SFabien Sanglard kGroupChoice, 32*3f982cf4SFabien Sanglard kGroupnameChoice, 33*3f982cf4SFabien Sanglard kTaggedType, 34*3f982cf4SFabien Sanglard }; 35*3f982cf4SFabien Sanglard enum class Op { 36*3f982cf4SFabien Sanglard kNone, // not specified 37*3f982cf4SFabien Sanglard kInclusiveRange, // .. 38*3f982cf4SFabien Sanglard kExclusiveRange, // ... 39*3f982cf4SFabien Sanglard kSize, // .size 40*3f982cf4SFabien Sanglard kBits, // .bits 41*3f982cf4SFabien Sanglard kRegexp, // .regexp 42*3f982cf4SFabien Sanglard kCbor, // .cbor 43*3f982cf4SFabien Sanglard kCborseq, // .cborseq 44*3f982cf4SFabien Sanglard kWithin, // .within 45*3f982cf4SFabien Sanglard kAnd, // .and 46*3f982cf4SFabien Sanglard kLess, // .lt 47*3f982cf4SFabien Sanglard kLessOrEqual, // .lt 48*3f982cf4SFabien Sanglard kGreater, // .gt 49*3f982cf4SFabien Sanglard kGreaterOrEqual, // .ge 50*3f982cf4SFabien Sanglard kEqual, // .eq 51*3f982cf4SFabien Sanglard kNotEqual, // .ne 52*3f982cf4SFabien Sanglard kDefault, // .default 53*3f982cf4SFabien Sanglard }; 54*3f982cf4SFabien Sanglard struct TaggedType { 55*3f982cf4SFabien Sanglard uint64_t tag_value; 56*3f982cf4SFabien Sanglard CddlType* type; 57*3f982cf4SFabien Sanglard }; 58*3f982cf4SFabien Sanglard CddlType(); 59*3f982cf4SFabien Sanglard ~CddlType(); 60*3f982cf4SFabien Sanglard 61*3f982cf4SFabien Sanglard Which which; 62*3f982cf4SFabien Sanglard union { 63*3f982cf4SFabien Sanglard // A direct choice comes from the CDDL syntax "a-type / b-type / c-type". 64*3f982cf4SFabien Sanglard // This is in contrast to a "group choice". 65*3f982cf4SFabien Sanglard std::vector<CddlType*> direct_choice; 66*3f982cf4SFabien Sanglard 67*3f982cf4SFabien Sanglard // A literal value (number, text, or bytes) stored as its original string 68*3f982cf4SFabien Sanglard // form. 69*3f982cf4SFabien Sanglard std::string value; 70*3f982cf4SFabien Sanglard 71*3f982cf4SFabien Sanglard std::string id; 72*3f982cf4SFabien Sanglard CddlGroup* map; 73*3f982cf4SFabien Sanglard CddlGroup* array; 74*3f982cf4SFabien Sanglard 75*3f982cf4SFabien Sanglard // A group choice comes from the CDDL syntax: 76*3f982cf4SFabien Sanglard // a-group = ( 77*3f982cf4SFabien Sanglard // key1: uint, key2: text // 78*3f982cf4SFabien Sanglard // key3: float, key4: bytes // 79*3f982cf4SFabien Sanglard // key5: text 80*3f982cf4SFabien Sanglard // ) 81*3f982cf4SFabien Sanglard CddlGroup* group_choice; 82*3f982cf4SFabien Sanglard TaggedType tagged_type; 83*3f982cf4SFabien Sanglard }; 84*3f982cf4SFabien Sanglard 85*3f982cf4SFabien Sanglard Op op; 86*3f982cf4SFabien Sanglard CddlType* constraint_type; 87*3f982cf4SFabien Sanglard absl::optional<uint64_t> type_key; 88*3f982cf4SFabien Sanglard }; 89*3f982cf4SFabien Sanglard 90*3f982cf4SFabien Sanglard // Override for << operator to simplify logging. 91*3f982cf4SFabien Sanglard // NOTE: If a new enum value is added without modifying this operator, it will 92*3f982cf4SFabien Sanglard // lead to a compilation failure because an enum class is used. 93*3f982cf4SFabien Sanglard inline std::ostream& operator<<(std::ostream& os, 94*3f982cf4SFabien Sanglard const CddlType::Which& which) { 95*3f982cf4SFabien Sanglard switch (which) { 96*3f982cf4SFabien Sanglard case CddlType::Which::kDirectChoice: 97*3f982cf4SFabien Sanglard os << "kDirectChoice"; 98*3f982cf4SFabien Sanglard break; 99*3f982cf4SFabien Sanglard case CddlType::Which::kValue: 100*3f982cf4SFabien Sanglard os << "kValue"; 101*3f982cf4SFabien Sanglard break; 102*3f982cf4SFabien Sanglard case CddlType::Which::kId: 103*3f982cf4SFabien Sanglard os << "kId"; 104*3f982cf4SFabien Sanglard break; 105*3f982cf4SFabien Sanglard case CddlType::Which::kMap: 106*3f982cf4SFabien Sanglard os << "kMap"; 107*3f982cf4SFabien Sanglard break; 108*3f982cf4SFabien Sanglard case CddlType::Which::kArray: 109*3f982cf4SFabien Sanglard os << "kArray"; 110*3f982cf4SFabien Sanglard break; 111*3f982cf4SFabien Sanglard case CddlType::Which::kGroupChoice: 112*3f982cf4SFabien Sanglard os << "kGroupChoice"; 113*3f982cf4SFabien Sanglard break; 114*3f982cf4SFabien Sanglard case CddlType::Which::kGroupnameChoice: 115*3f982cf4SFabien Sanglard os << "kGroupnameChoice"; 116*3f982cf4SFabien Sanglard break; 117*3f982cf4SFabien Sanglard case CddlType::Which::kTaggedType: 118*3f982cf4SFabien Sanglard os << "kTaggedType"; 119*3f982cf4SFabien Sanglard break; 120*3f982cf4SFabien Sanglard } 121*3f982cf4SFabien Sanglard return os; 122*3f982cf4SFabien Sanglard } 123*3f982cf4SFabien Sanglard 124*3f982cf4SFabien Sanglard // Represets a group defined in CDDL. 125*3f982cf4SFabien Sanglard // TODO(btolsch): group choices 126*3f982cf4SFabien Sanglard struct CddlGroup { 127*3f982cf4SFabien Sanglard struct Entry { 128*3f982cf4SFabien Sanglard enum class Which { 129*3f982cf4SFabien Sanglard kUninitialized = 0, 130*3f982cf4SFabien Sanglard kType, 131*3f982cf4SFabien Sanglard kGroup, 132*3f982cf4SFabien Sanglard }; 133*3f982cf4SFabien Sanglard struct EntryType { 134*3f982cf4SFabien Sanglard std::string opt_key; 135*3f982cf4SFabien Sanglard absl::optional<uint64_t> integer_key; 136*3f982cf4SFabien Sanglard CddlType* value; 137*3f982cf4SFabien Sanglard }; 138*3f982cf4SFabien Sanglard Entry(); 139*3f982cf4SFabien Sanglard ~Entry(); 140*3f982cf4SFabien Sanglard 141*3f982cf4SFabien Sanglard // Minimum number of times that this entry can be repeated. 142*3f982cf4SFabien Sanglard uint32_t opt_occurrence_min; 143*3f982cf4SFabien Sanglard 144*3f982cf4SFabien Sanglard // Maximum number of times that this entry can be repeated. 145*3f982cf4SFabien Sanglard uint32_t opt_occurrence_max; 146*3f982cf4SFabien Sanglard 147*3f982cf4SFabien Sanglard // Signifies whether an occurrence opperator is present or not. 148*3f982cf4SFabien Sanglard bool occurrence_specified; 149*3f982cf4SFabien Sanglard 150*3f982cf4SFabien Sanglard // Value to represent when opt_occurrence_min is unbounded. 151*3f982cf4SFabien Sanglard static constexpr uint32_t kOccurrenceMinUnbounded = 0; 152*3f982cf4SFabien Sanglard 153*3f982cf4SFabien Sanglard // Value to represent when opt_occurrence_max is unbounded. 154*3f982cf4SFabien Sanglard static constexpr uint32_t kOccurrenceMaxUnbounded = 155*3f982cf4SFabien Sanglard std::numeric_limits<uint32_t>::max(); 156*3f982cf4SFabien Sanglard 157*3f982cf4SFabien Sanglard Which which = Which::kUninitialized; 158*3f982cf4SFabien Sanglard union { 159*3f982cf4SFabien Sanglard EntryType type; 160*3f982cf4SFabien Sanglard CddlGroup* group; 161*3f982cf4SFabien Sanglard }; 162*3f982cf4SFabien Sanglard HasOccurrenceOperatorCddlGroup::Entry163*3f982cf4SFabien Sanglard bool HasOccurrenceOperator() const { return occurrence_specified; } 164*3f982cf4SFabien Sanglard }; 165*3f982cf4SFabien Sanglard 166*3f982cf4SFabien Sanglard std::vector<std::unique_ptr<Entry>> entries; 167*3f982cf4SFabien Sanglard }; 168*3f982cf4SFabien Sanglard 169*3f982cf4SFabien Sanglard // Override for << operator to simplify logging. 170*3f982cf4SFabien Sanglard // NOTE: If a new enum value is added without modifying this operator, it will 171*3f982cf4SFabien Sanglard // lead to a compilation failure because an enum class is used. 172*3f982cf4SFabien Sanglard inline std::ostream& operator<<(std::ostream& os, 173*3f982cf4SFabien Sanglard const CddlGroup::Entry::Which& which) { 174*3f982cf4SFabien Sanglard switch (which) { 175*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kUninitialized: 176*3f982cf4SFabien Sanglard os << "kUninitialized"; 177*3f982cf4SFabien Sanglard break; 178*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kType: 179*3f982cf4SFabien Sanglard os << "kType"; 180*3f982cf4SFabien Sanglard break; 181*3f982cf4SFabien Sanglard case CddlGroup::Entry::Which::kGroup: 182*3f982cf4SFabien Sanglard os << "kGroup"; 183*3f982cf4SFabien Sanglard break; 184*3f982cf4SFabien Sanglard } 185*3f982cf4SFabien Sanglard return os; 186*3f982cf4SFabien Sanglard } 187*3f982cf4SFabien Sanglard 188*3f982cf4SFabien Sanglard // Represents all CDDL definitions. 189*3f982cf4SFabien Sanglard struct CddlSymbolTable { 190*3f982cf4SFabien Sanglard // Set of all CDDL types. 191*3f982cf4SFabien Sanglard std::vector<std::unique_ptr<CddlType>> types; 192*3f982cf4SFabien Sanglard 193*3f982cf4SFabien Sanglard // Set of all CDDL groups. 194*3f982cf4SFabien Sanglard std::vector<std::unique_ptr<CddlGroup>> groups; 195*3f982cf4SFabien Sanglard 196*3f982cf4SFabien Sanglard // Map from name of a type to the object that represents it. 197*3f982cf4SFabien Sanglard std::map<std::string, CddlType*> type_map; 198*3f982cf4SFabien Sanglard 199*3f982cf4SFabien Sanglard // Map from name of a group to the object that represents it. 200*3f982cf4SFabien Sanglard std::map<std::string, CddlGroup*> group_map; 201*3f982cf4SFabien Sanglard }; 202*3f982cf4SFabien Sanglard 203*3f982cf4SFabien Sanglard // Represents a C++ Type, as translated from CDDL. 204*3f982cf4SFabien Sanglard struct CppType { 205*3f982cf4SFabien Sanglard // Data type for this C++ type. 206*3f982cf4SFabien Sanglard enum class Which { 207*3f982cf4SFabien Sanglard kUninitialized = 0, 208*3f982cf4SFabien Sanglard kUint64, 209*3f982cf4SFabien Sanglard kString, 210*3f982cf4SFabien Sanglard kBytes, 211*3f982cf4SFabien Sanglard kVector, 212*3f982cf4SFabien Sanglard kEnum, 213*3f982cf4SFabien Sanglard kStruct, 214*3f982cf4SFabien Sanglard kOptional, 215*3f982cf4SFabien Sanglard kDiscriminatedUnion, 216*3f982cf4SFabien Sanglard kTaggedType, 217*3f982cf4SFabien Sanglard }; 218*3f982cf4SFabien Sanglard 219*3f982cf4SFabien Sanglard struct Vector { 220*3f982cf4SFabien Sanglard CppType* element_type; 221*3f982cf4SFabien Sanglard 222*3f982cf4SFabien Sanglard // Minimum length for the vector. 223*3f982cf4SFabien Sanglard uint32_t min_length; 224*3f982cf4SFabien Sanglard 225*3f982cf4SFabien Sanglard // Maximum length for the vector. 226*3f982cf4SFabien Sanglard uint32_t max_length; 227*3f982cf4SFabien Sanglard 228*3f982cf4SFabien Sanglard // Value to represent when opt_occurrence_min is unbounded. 229*3f982cf4SFabien Sanglard static constexpr uint32_t kMinLengthUnbounded = 230*3f982cf4SFabien Sanglard CddlGroup::Entry::kOccurrenceMinUnbounded; 231*3f982cf4SFabien Sanglard 232*3f982cf4SFabien Sanglard // Value to represent when opt_occurrence_max is unbounded. 233*3f982cf4SFabien Sanglard static constexpr uint32_t kMaxLengthUnbounded = 234*3f982cf4SFabien Sanglard CddlGroup::Entry::kOccurrenceMaxUnbounded; 235*3f982cf4SFabien Sanglard }; 236*3f982cf4SFabien Sanglard 237*3f982cf4SFabien Sanglard struct Enum { 238*3f982cf4SFabien Sanglard std::string name; 239*3f982cf4SFabien Sanglard std::vector<CppType*> sub_members; 240*3f982cf4SFabien Sanglard std::vector<std::pair<std::string, uint64_t>> members; 241*3f982cf4SFabien Sanglard }; 242*3f982cf4SFabien Sanglard 243*3f982cf4SFabien Sanglard // Represents a C++ Struct. 244*3f982cf4SFabien Sanglard struct Struct { 245*3f982cf4SFabien Sanglard enum class KeyType { 246*3f982cf4SFabien Sanglard kMap, 247*3f982cf4SFabien Sanglard kArray, 248*3f982cf4SFabien Sanglard kPlainGroup, 249*3f982cf4SFabien Sanglard }; 250*3f982cf4SFabien Sanglard // Contains a member of a C++ Struct. 251*3f982cf4SFabien Sanglard struct CppMember { 252*3f982cf4SFabien Sanglard // Constructs a new CppMember from the required fields. This constructor 253*3f982cf4SFabien Sanglard // is needed for vector::emplace_back(...). CppMemberCppType::Struct::CppMember254*3f982cf4SFabien Sanglard CppMember(std::string name, 255*3f982cf4SFabien Sanglard absl::optional<uint64_t> integer_key, 256*3f982cf4SFabien Sanglard CppType* type) { 257*3f982cf4SFabien Sanglard this->name = std::move(name); 258*3f982cf4SFabien Sanglard this->integer_key = integer_key; 259*3f982cf4SFabien Sanglard this->type = type; 260*3f982cf4SFabien Sanglard } 261*3f982cf4SFabien Sanglard 262*3f982cf4SFabien Sanglard // Name visible to callers of the generated C++ methods. 263*3f982cf4SFabien Sanglard std::string name; 264*3f982cf4SFabien Sanglard 265*3f982cf4SFabien Sanglard // When present, this key is used in place of the name for serialialized 266*3f982cf4SFabien Sanglard // messages. This should only be the case for integer-keyed group entries. 267*3f982cf4SFabien Sanglard absl::optional<uint64_t> integer_key; 268*3f982cf4SFabien Sanglard 269*3f982cf4SFabien Sanglard // C++ Type this member represents. 270*3f982cf4SFabien Sanglard CppType* type; 271*3f982cf4SFabien Sanglard }; 272*3f982cf4SFabien Sanglard 273*3f982cf4SFabien Sanglard // Set of all members in this Struct. 274*3f982cf4SFabien Sanglard std::vector<CppMember> members; 275*3f982cf4SFabien Sanglard 276*3f982cf4SFabien Sanglard // Type of data structure being represented. 277*3f982cf4SFabien Sanglard KeyType key_type; 278*3f982cf4SFabien Sanglard }; 279*3f982cf4SFabien Sanglard 280*3f982cf4SFabien Sanglard struct DiscriminatedUnion { 281*3f982cf4SFabien Sanglard std::vector<CppType*> members; 282*3f982cf4SFabien Sanglard }; 283*3f982cf4SFabien Sanglard 284*3f982cf4SFabien Sanglard struct Bytes { 285*3f982cf4SFabien Sanglard absl::optional<size_t> fixed_size; 286*3f982cf4SFabien Sanglard }; 287*3f982cf4SFabien Sanglard 288*3f982cf4SFabien Sanglard struct TaggedType { 289*3f982cf4SFabien Sanglard uint64_t tag; 290*3f982cf4SFabien Sanglard CppType* real_type; 291*3f982cf4SFabien Sanglard }; 292*3f982cf4SFabien Sanglard 293*3f982cf4SFabien Sanglard CppType(); 294*3f982cf4SFabien Sanglard ~CppType(); 295*3f982cf4SFabien Sanglard 296*3f982cf4SFabien Sanglard void InitVector(); 297*3f982cf4SFabien Sanglard void InitEnum(); 298*3f982cf4SFabien Sanglard void InitStruct(); 299*3f982cf4SFabien Sanglard void InitDiscriminatedUnion(); 300*3f982cf4SFabien Sanglard void InitBytes(); 301*3f982cf4SFabien Sanglard 302*3f982cf4SFabien Sanglard Which which = Which::kUninitialized; 303*3f982cf4SFabien Sanglard std::string name; 304*3f982cf4SFabien Sanglard absl::optional<uint64_t> type_key; 305*3f982cf4SFabien Sanglard union { 306*3f982cf4SFabien Sanglard Vector vector_type; 307*3f982cf4SFabien Sanglard Enum enum_type; 308*3f982cf4SFabien Sanglard Struct struct_type; 309*3f982cf4SFabien Sanglard CppType* optional_type; 310*3f982cf4SFabien Sanglard DiscriminatedUnion discriminated_union; 311*3f982cf4SFabien Sanglard Bytes bytes_type; 312*3f982cf4SFabien Sanglard TaggedType tagged_type; 313*3f982cf4SFabien Sanglard }; 314*3f982cf4SFabien Sanglard }; 315*3f982cf4SFabien Sanglard 316*3f982cf4SFabien Sanglard // Override for << operator to simplify logging. 317*3f982cf4SFabien Sanglard // NOTE: If a new enum value is added without modifying this operator, it will 318*3f982cf4SFabien Sanglard // lead to a compilation failure because an enum class is used. 319*3f982cf4SFabien Sanglard inline std::ostream& operator<<(std::ostream& os, const CppType::Which& which) { 320*3f982cf4SFabien Sanglard switch (which) { 321*3f982cf4SFabien Sanglard case CppType::Which::kUint64: 322*3f982cf4SFabien Sanglard os << "kUint64"; 323*3f982cf4SFabien Sanglard break; 324*3f982cf4SFabien Sanglard case CppType::Which::kString: 325*3f982cf4SFabien Sanglard os << "kString"; 326*3f982cf4SFabien Sanglard break; 327*3f982cf4SFabien Sanglard case CppType::Which::kBytes: 328*3f982cf4SFabien Sanglard os << "kBytes"; 329*3f982cf4SFabien Sanglard break; 330*3f982cf4SFabien Sanglard case CppType::Which::kVector: 331*3f982cf4SFabien Sanglard os << "kVector"; 332*3f982cf4SFabien Sanglard break; 333*3f982cf4SFabien Sanglard case CppType::Which::kEnum: 334*3f982cf4SFabien Sanglard os << "kEnum"; 335*3f982cf4SFabien Sanglard break; 336*3f982cf4SFabien Sanglard case CppType::Which::kStruct: 337*3f982cf4SFabien Sanglard os << "kStruct"; 338*3f982cf4SFabien Sanglard break; 339*3f982cf4SFabien Sanglard case CppType::Which::kOptional: 340*3f982cf4SFabien Sanglard os << "kOptional"; 341*3f982cf4SFabien Sanglard break; 342*3f982cf4SFabien Sanglard case CppType::Which::kDiscriminatedUnion: 343*3f982cf4SFabien Sanglard os << "kDiscriminatedUnion"; 344*3f982cf4SFabien Sanglard break; 345*3f982cf4SFabien Sanglard case CppType::Which::kTaggedType: 346*3f982cf4SFabien Sanglard os << "kTaggedType"; 347*3f982cf4SFabien Sanglard break; 348*3f982cf4SFabien Sanglard case CppType::Which::kUninitialized: 349*3f982cf4SFabien Sanglard os << "kUninitialized"; 350*3f982cf4SFabien Sanglard break; 351*3f982cf4SFabien Sanglard } 352*3f982cf4SFabien Sanglard return os; 353*3f982cf4SFabien Sanglard } 354*3f982cf4SFabien Sanglard 355*3f982cf4SFabien Sanglard struct CppSymbolTable { 356*3f982cf4SFabien Sanglard public: 357*3f982cf4SFabien Sanglard std::vector<std::unique_ptr<CppType>> cpp_types; 358*3f982cf4SFabien Sanglard std::map<std::string, CppType*> cpp_type_map; 359*3f982cf4SFabien Sanglard 360*3f982cf4SFabien Sanglard std::vector<CppType*> TypesWithId(); 361*3f982cf4SFabien Sanglard 362*3f982cf4SFabien Sanglard private: 363*3f982cf4SFabien Sanglard std::vector<CppType*> TypesWithId_; 364*3f982cf4SFabien Sanglard }; 365*3f982cf4SFabien Sanglard 366*3f982cf4SFabien Sanglard std::pair<bool, CddlSymbolTable> BuildSymbolTable(const AstNode& rules); 367*3f982cf4SFabien Sanglard std::pair<bool, CppSymbolTable> BuildCppTypes( 368*3f982cf4SFabien Sanglard const CddlSymbolTable& cddl_table); 369*3f982cf4SFabien Sanglard bool ValidateCppTypes(const CppSymbolTable& cpp_symbols); 370*3f982cf4SFabien Sanglard void DumpType(CddlType* type, int indent_level = 0); 371*3f982cf4SFabien Sanglard void DumpGroup(CddlGroup* group, int indent_level = 0); 372*3f982cf4SFabien Sanglard void DumpSymbolTable(CddlSymbolTable* table); 373*3f982cf4SFabien Sanglard 374*3f982cf4SFabien Sanglard #endif // TOOLS_CDDL_SEMA_H_ 375