idl_parser.cpp revision 29574282a283ddc7904d096d27b783b794da7e91
126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen/* 226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Copyright 2014 Google Inc. All rights reserved. 326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Licensed under the Apache License, Version 2.0 (the "License"); 526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * you may not use this file except in compliance with the License. 626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * You may obtain a copy of the License at 726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * http://www.apache.org/licenses/LICENSE-2.0 926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 1026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Unless required by applicable law or agreed to in writing, software 1126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * distributed under the License is distributed on an "AS IS" BASIS, 1226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * See the License for the specific language governing permissions and 1426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * limitations under the License. 1526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen */ 1626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include <algorithm> 18df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez#include <list> 1926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#ifdef _WIN32 21d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#if !defined(_USE_MATH_DEFINES) 22d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#define _USE_MATH_DEFINES // For M_PI. 23d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // !defined(_USE_MATH_DEFINES) 24d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // _WIN32 25d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 26d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#include <math.h> 27d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 2826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/idl.h" 2926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/util.h" 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennamespace flatbuffers { 3226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char *const kTypeNames[] = { 3448dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 3548dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 3626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 3726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen nullptr 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char kTypeSizes[] = { 4248dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 43557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen sizeof(CTYPE), 4426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 4526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 4626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// The enums in the reflection schema should match the ones we use internally. 4981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Compare the last element to check if these go out of sync. 5081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenstatic_assert(BASE_TYPE_UNION == 51622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen static_cast<BaseType>(reflection::Union), 5281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen "enums don't match"); 5381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 54451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// Any parsing calls have to be wrapped in this macro, which automates 55451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// handling of recursive error checking a bit. It will check the received 56451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// CheckedError object, and return straight away on error. 5740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define ECHECK(call) { auto ce = (call); if (ce.Check()) return ce; } 58451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen 59451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// These two functions are called hundreds of times below, so define a short 60451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// form: 6140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define NEXT() ECHECK(Next()) 6240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define EXPECT(tok) ECHECK(Expect(tok)) 6340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 64f6416d847186802e03d2fa3c05963ec377c146fcBen Hamiltonstatic bool ValidateUTF8(const std::string &str) { 65f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char *s = &str[0]; 66f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char * const sEnd = s + str.length(); 67f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton while (s < sEnd) { 68f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (FromUTF8(&s) < 0) { 69f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return false; 70f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 71f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 72f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return true; 73f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton} 74f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton 7540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Error(const std::string &msg) { 7640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; 7740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #ifdef _WIN32 7840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += "(" + NumToString(line_) + ")"; // MSVC alike 7940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #else 8040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_being_parsed_.length()) error_ += ":"; 8140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += NumToString(line_) + ":0"; // gcc alike 8240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #endif 8340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += ": error: " + msg; 8440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return CheckedError(true); 8526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 8626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmersseninline CheckedError NoError() { return CheckedError(false); } 8840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 8926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 9040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::CheckBitsFit(int64_t val, size_t bits) { 913400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // Left-shifting a 64-bit value by 64 bits or more is undefined 923400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // behavior (C99 6.5.7), so check *before* we shift. 933400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield if (bits < 64) { 943400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // Bits we allow to be used. 953400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield auto mask = static_cast<int64_t>((1ull << bits) - 1); 963400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield if ((val & ~mask) != 0 && // Positive or unsigned. 973400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield (val | mask) != -1) // Negative. 983400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield return Error("constant does not fit in a " + NumToString(bits) + 993400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield "-bit field"); 1003400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield } 10140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 10226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 10326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 10540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<typename T> inline CheckedError atot(const char *s, Parser &parser, 10640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen T *val) { 10740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t i = StringToInt(s); 10840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(parser.CheckBitsFit(i, sizeof(T) * 8)); 10940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = (T)i; 11040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssentemplate<> inline CheckedError atot<uint64_t>(const char *s, Parser &parser, 11329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t *val) { 11429574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (void)parser; 11529574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen *val = StringToUInt(s); 11629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen return NoError(); 11729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen} 11840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<bool>(const char *s, Parser &parser, 11940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool *val) { 12040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = 0 != atoi(s); 12240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 12440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<float>(const char *s, Parser &parser, 12540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen float *val) { 12640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = static_cast<float>(strtod(s, nullptr)); 12840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<double>(const char *s, Parser &parser, 13140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen double *val) { 13240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = strtod(s, nullptr); 13440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 13840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Offset<void> *val) { 13940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 14040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = Offset<void>(atoi(s)); 14140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 14226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Namespace::GetFullyQualifiedName(const std::string &name, 14594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen size_t max_components) const { 14694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Early exit if we don't have a defined namespace. 14794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (components.size() == 0 || !max_components) { 14894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return name; 14994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::stringstream stream; 15194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t i = 0; i < std::min(components.size(), max_components); 15294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen i++) { 15394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (i) { 15494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "."; 15594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << components[i]; 15794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1588c1a723ba55d1574590eba801d64afab9c49e017Wouter van Oortmerssen if (name.length()) stream << "." << name; 15994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return stream.str(); 16094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 16194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 16526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 16626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 16726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 16826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 16926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 17026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 17126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Identifier, 260, "identifier") \ 17226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Table, 261, "table") \ 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Struct, 262, "struct") \ 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Enum, 263, "enum") \ 17526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Union, 264, "union") \ 17626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(NameSpace, 265, "namespace") \ 1775da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(RootType, 266, "root_type") \ 1785da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(FileIdentifier, 267, "file_identifier") \ 179be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen TD(FileExtension, 268, "file_extension") \ 1800952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen TD(Include, 269, "include") \ 181049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen TD(Attribute, 270, "attribute") \ 1821a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen TD(Null, 271, "null") \ 1833f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen TD(Service, 272, "rpc_service") \ 1843f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen TD(NativeInclude, 273, "native_include") 1858f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 1868f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 1878f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 18975349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 19026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 19248dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 193557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen kToken ## ENUM, 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 19526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 19626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 19826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 20348dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 20448dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 20526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 20626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 20726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 20926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 2108e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 21126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 21226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 21326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 21426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 21526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 21626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 21794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Parser::TokenToStringId(int t) { 21894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return TokenToString(t) + (t == kTokenIdentifier ? ": " + attribute_ : ""); 21994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 22094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 221ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 22229574282a283ddc7904d096d27b783b794da7e91Wouter van OortmerssenCheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) { 223ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 22430013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if (!isxdigit(static_cast<const unsigned char>(cursor_[i]))) 22540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("escape code must be followed by " + NumToString(nibbles) + 22640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " hex digits"); 2277cf74cb8644262f8ca02d69705bbc394d66514ceHiroshi Matsunaga std::string target(cursor_, cursor_ + nibbles); 228b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain *val = StringToUInt(target.c_str(), nullptr, 16); 229ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 23040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 231ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 232ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 233cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <OliCheckedError Parser::SkipByteOrderMark() { 234cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError(); 235cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli cursor_++; 236f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbb) return Error("invalid utf-8 byte order mark"); 237f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 238f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbf) return Error("invalid utf-8 byte order mark"); 239f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 240cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli return NoError(); 241cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli} 242cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli 243fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssenbool IsIdentifierStart(char c) { 244fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen return isalpha(static_cast<unsigned char>(c)) || c == '_'; 245fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen} 246fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen 24740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Next() { 24826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 24926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 25094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.clear(); 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 25226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 25326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 25426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 25540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return NoError(); 25626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 25726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 25840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': 25940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case ',': case ':': case ';': case '=': return NoError(); 26026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 26130013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError(); 26240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("floating point constant can\'t start with \".\""); 26326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 2646704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield case '\'': { 2656704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int unicode_high_surrogate = -1; 2666704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield 26794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != c) { 26826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 26940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character in string constant"); 27026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 27126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 2726704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1 && 2736704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield *cursor_ != 'u') { 2746704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2756704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 2766704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 27726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 27826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 27926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 28026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 281ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 282ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 28326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 28494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen case '\'': attribute_ += '\''; cursor_++; break; 28526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 286ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 287ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 288ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 28929574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 29040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(2, &val)); 29140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ += static_cast<char>(val); 292ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 293ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 294ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 295ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 29629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 29740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(4, &val)); 2986704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (val >= 0xD800 && val <= 0xDBFF) { 2996704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3006704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3016704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (multiple high surrogates)"); 3026704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 303e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen unicode_high_surrogate = static_cast<int>(val); 3046704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3056704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else if (val >= 0xDC00 && val <= 0xDFFF) { 3066704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate == -1) { 3076704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3086704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired low surrogate)"); 3096704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3106704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int code_point = 0x10000 + 3116704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ((unicode_high_surrogate & 0x03FF) << 10) + 3126704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield (val & 0x03FF); 3136704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(code_point, &attribute_); 3146704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield unicode_high_surrogate = -1; 3156704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3166704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3176704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3186704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3196704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3206704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3216704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(static_cast<int>(val), &attribute_); 3226704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 323ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 324ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 32540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen default: return Error("unknown escape code in string constant"); 32626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 3286704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3296704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3306704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3316704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 33326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 33426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3356704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3366704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3376704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3386704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 340f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) { 341f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return Error("illegal UTF-8 sequence"); 342f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 34326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 34440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 3456704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 34626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 34726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 34826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 349a8d6962ac2fbf5075ee5f58877d488eb74ed32dfMormegil while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 35026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 35107d5965c812fa5e82dc4d3eb32b37540b7c91598Zbigniew Mandziejewicz if (cursor_ != source_ && !seen_newline) 35240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 35340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "a documentation comment should be on a line on its own"); 354730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez doc_comment_.push_back(std::string(start + 1, cursor_)); 35526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 35626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 35794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (*cursor_ == '*') { 35894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: make nested. 36094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != '*' || cursor_[1] != '/') { 361ab51b030939e02e55cac6f9e779d8696013819a9Wouter van Oortmerssen if (*cursor_ == '\n') line_++; 36240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!*cursor_) return Error("end of file in comment"); 36394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 36494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 36594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_ += 2; 36694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen break; 36726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 36826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 36926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 370fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(c)) { 37126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 37226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 37326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 37426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 37526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 37626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 37726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // First, see if it is a type keyword from the table of types: 37848dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 37948dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 38026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == IDLTYPE) { \ 38126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kToken ## ENUM; \ 38240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); \ 38326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 38426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 38526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 38626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If it's a boolean constant keyword, turn those into integers, 38726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // which simplifies our logic downstream. 38826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "true" || attribute_ == "false") { 38926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ = NumToString(attribute_ == "true"); 39026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 39140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 39326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Check for declaration keywords: 39440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "table") { 39540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenTable; 39640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 39840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "struct") { 39940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenStruct; 40040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "enum") { 40340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenEnum; 40440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "union") { 40740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenUnion; 40840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "namespace") { 41140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenNameSpace; 41240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "root_type") { 41540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenRootType; 41640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "include") { 41940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenInclude; 42040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 42140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 42240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "attribute") { 42340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenAttribute; 42440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 42540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 4265da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_identifier") { 4275da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileIdentifier; 42840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4295da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 4305da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_extension") { 4315da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileExtension; 43240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4335da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 434049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (attribute_ == "null") { 435049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen token_ = kTokenNull; 436049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return NoError(); 437049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 4381a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (attribute_ == "rpc_service") { 4391a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen token_ = kTokenService; 4401a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 4411a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } 4423f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen if (attribute_ == "native_include") { 4433f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen token_ = kTokenNativeInclude; 4443f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen return NoError(); 4453f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen } 44626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If not, it is a user-defined identifier: 44726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 44840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 44926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 45026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 45129574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen if (c == '-' && *cursor_ == '0' && 45229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (cursor_[1] == 'x' || cursor_[1] == 'X')) { 453f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++start; 454f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++cursor_; 455f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman attribute_.append(&c, &c + 1); 456f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman c = '0'; 457f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman } 45894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { 45994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 46094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 46194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.append(start + 2, cursor_); 46229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen attribute_ = NumToString(static_cast<int64_t>( 46329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen StringToUInt(attribute_.c_str(), nullptr, 16))); 46494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen token_ = kTokenIntegerConstant; 46540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 46694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 46726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 46894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.' || *cursor_ == 'e' || *cursor_ == 'E') { 46994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.') { 47094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 47194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 47294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 47393df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 47493df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 47593df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 47693df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 47793df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 47893df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 47993df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 48026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 48126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 48226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 48326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 48426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 48540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 48626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 48726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 48826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 48926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 49040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character: " + ch); 49126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 49426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 49540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen// Check if a given token is next. 49640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssenbool Parser::Is(int t) { 49740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return t == token_; 49826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 49926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 50026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 50140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Expect(int t) { 50226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 50340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("expecting: " + TokenToString(t) + " instead got: " + 50440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 50526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 50640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 50740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 50826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 50926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 51040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 51140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { 51240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 51339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += "."; 51439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += attribute_; 51539833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen if (last) *last = attribute_; 51640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 51739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen } 51840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 51939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 52039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 52139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van OortmerssenEnumDef *Parser::LookupEnum(const std::string &id) { 52294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 52394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int components = static_cast<int>(namespaces_.back()->components.size()); 52494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components >= 0; components--) { 52540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto ed = enums_.Lookup( 52640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(id, components)); 52794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (ed) return ed; 52894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 52994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return nullptr; 53039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 53139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 53240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeIdent(Type &type) { 53339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen std::string id = attribute_; 53440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 53540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 53639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(id); 537d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def) { 538d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type = enum_def->underlying_type; 539d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 540d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 541d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 54239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen type.struct_def = LookupCreateStruct(id); 543d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 54440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 545d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 546d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 54726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 54840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseType(Type &type) { 54926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) { 55026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.base_type = static_cast<BaseType>(token_ - kTokenNONE); 55140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 55226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 55326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == kTokenIdentifier) { 55440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(type)); 55526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == '[') { 55640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 55726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type subtype; 55840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(subtype)); 55926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 56026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this, but it will complicate things, and it's 56126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // easier to work around with a struct around the inner vector. 56240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 56340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested vector types not supported (wrap in table first)."); 56426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 5653fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 56626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.element = subtype.base_type; 56740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 56826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 56940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal type syntax"); 57026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 57326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 57426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 57540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 57640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const Type &type, FieldDef **dest) { 57726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 57826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 57926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 58026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 581df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez field.file = struct_def.file; 58226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 58326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 58426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 58526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 58626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 58726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 58826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 58926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 5901256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 59126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 59226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 59326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 59440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field already exists: " + name); 59540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &field; 59640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 59726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 59826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 59940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseField(StructDef &struct_def) { 60026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 601730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez std::vector<std::string> dc = doc_comment_; 60240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 60340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(':'); 60426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 60540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(type)); 60626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 60726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 60840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("structs_ may contain only scalar or struct fields"); 60926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6109140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 61126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 61226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 6139e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // with a special suffix. 6149e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 6159e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type.enum_def->underlying_type, &typefield)); 61668bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } else if (type.base_type == BASE_TYPE_VECTOR && 61768bbe983e9819bcbcd214cf84d73a440863ed6caBei Li type.element == BASE_TYPE_UNION) { 61868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // Only cpp supports the union vector feature so far. 61968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li if (opts.lang_to_generate != IDLOptions::kCpp) { 62068bbe983e9819bcbcd214cf84d73a440863ed6caBei Li return Error("Vectors of unions are not yet supported in all " 62168bbe983e9819bcbcd214cf84d73a440863ed6caBei Li "the specified programming languages."); 62268bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } 62368bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // For vector of union fields, add a second auto-generated vector field to 62468bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // hold the types, with a special suffix. 62568bbe983e9819bcbcd214cf84d73a440863ed6caBei Li Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def); 62668bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector.element = BASE_TYPE_UTYPE; 62768bbe983e9819bcbcd214cf84d73a440863ed6caBei Li ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 62868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector, &typefield)); 62926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 63026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 63140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field; 63240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(AddField(struct_def, name, type, &field)); 63326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 63426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 63540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 63615dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 63740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("default values currently only supported for scalars"); 63840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(field->value)); 639fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen } 640fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (IsFloat(field->value.type.base_type)) { 641fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (!strpbrk(field->value.constant.c_str(), ".eE")) 642fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen field->value.constant += ".0"; 64326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 64426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6457b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen if (type.enum_def && 6467b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen IsScalar(type.base_type) && 6477b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !struct_def.fixed && 6487b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !type.enum_def->attributes.Lookup("bit_flags") && 649d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen !type.enum_def->ReverseLookup(static_cast<int>( 65040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StringToInt(field->value.constant.c_str())))) 65140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum " + type.enum_def->name + 6527b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen " does not have a declaration for this field\'s default of " + 65340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant); 6547b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen 65540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = dc; 656e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&field->attributes)); 65740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 65840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto hash_name = field->attributes.Lookup("hash"); 659d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (hash_name) { 660d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (type.base_type) { 661d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 662d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 663d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 66440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 32 bit types: " + 665d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 666d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 667d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 668d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 669d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 670d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 67140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 64 bit types: " + 672d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 673d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 674d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 675d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 67640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 67740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "only int, uint, long and ulong data types support hashing."); 678d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 679d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 680dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen auto cpp_type = field->attributes.Lookup("cpp_type"); 681dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (cpp_type) { 682dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (!hash_name) 683dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen return Error("cpp_type can only be used with a hashed field"); 684dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen } 68540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->deprecated && struct_def.fixed) 68640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("can't deprecate fields in a struct"); 68740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = field->attributes.Lookup("required") != nullptr; 68840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->required && (struct_def.fixed || 68940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(field->value.type.base_type))) 69040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only non-scalar fields in tables may be 'required'"); 69140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->key = field->attributes.Lookup("key") != nullptr; 69240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->key) { 6933550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen if (struct_def.has_key) 69440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only one field may be set as 'key'"); 6953550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen struct_def.has_key = true; 69640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(field->value.type.base_type)) { 69740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = true; 69840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_STRING) 69940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("'key' field must be string or scalar type"); 7003550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 7013550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 702641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 703641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen field->native_inline = field->attributes.Lookup("native_inline") != nullptr; 704641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen if (field->native_inline && !IsStruct(field->value.type)) 705641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen return Error("native_inline can only be defined on structs'"); 706641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 70740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto nested = field->attributes.Lookup("nested_flatbuffer"); 7083e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 7093e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 71040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 71140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute must be a string (the root type)"); 71240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 71340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 71440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 71540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute may only apply to a vector of ubyte"); 7163e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 7173e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 7183e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 7193e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 72026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 7219140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 7229140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 7239140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 72440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto attr = field->attributes.Lookup("id"); 7259140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 7269140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 7279140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 7289140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 7299140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 7309140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 7319140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7329140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7339140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 73440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 73540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 73626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 73726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 73840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 7399e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen size_t parent_fieldn, 7409e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen const StructDef *parent_struct_def) { 74126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 74226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 74326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 7449e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen std::string constant; 745eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Find corresponding type field we may have already parsed. 746eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (auto elem = field_stack_.rbegin(); 747eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen elem != field_stack_.rbegin() + parent_fieldn; ++elem) { 748eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto &type = elem->second->value.type; 749eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UTYPE && 750eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen type.enum_def == val.type.enum_def) { 751eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen constant = elem->first.constant; 752eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen break; 753eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 754eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 755eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (constant.empty()) { 7569e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // We haven't seen the type field yet. Sadly a lot of JSON writers 7579e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // output these in alphabetical order, meaning it comes after this 7589e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // value. So we scan past the value to find it, then come back here. 7599e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_name = field->name + UnionTypeFieldSuffix(); 7609e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(parent_struct_def); 7619e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_field = parent_struct_def->fields.Lookup(type_name); 7629e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(type_field); // Guaranteed by ParseField(). 7639e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Remember where we are in the source file, so we can come back here. 7649e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto backup = *static_cast<ParserState *>(this); 7659e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(SkipAnyJsonValue()); // The table. 7669e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(','); 7679e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto next_name = attribute_; 7689e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (Is(kTokenStringConstant)) { 7699e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen NEXT(); 7709e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7719e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(kTokenIdentifier); 7729e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 7739e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (next_name != type_name) 7749e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen return Error("missing type field after this union value: " + 7759e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type_name); 7769e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(':'); 7779e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen Value type_val = type_field->value; 7789e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 7799e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = type_val.constant; 7809e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Got the information we needed, now rewind: 7819e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen *static_cast<ParserState *>(this) = backup; 7829e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 78340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uint8_t enum_idx; 7849e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(atot(constant.c_str(), *this, &enum_idx)); 7853fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 78640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("illegal type id for: " + field->name); 78740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr)); 78826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 78926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 79026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 79140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 79226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 79326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 79426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto s = attribute_; 79540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 79626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 79726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 79826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 79926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 80040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('['); 80140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t off; 80240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseVector(val.type.VectorType(), &off)); 80340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val.constant = NumToString(off); 80426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 80526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 806d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 807d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: 808d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 809d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 810d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (field && field->attributes.Lookup("hash") && 811d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 81240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHash(val, field)); 813d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } else { 81440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 815d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 816d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 817d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 81826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 81940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 82026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 82126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 82240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 82326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 82426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 82526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 8264d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(val.constant.length() == struct_def.bytesize); 82726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 8284d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 8294d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 83026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 83126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 83226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 83340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 83440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t *ovalue) { 83540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 83626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size_t fieldn = 0; 8376c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 83840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((!opts.strict_json || !fieldn) && Is('}')) { NEXT(); break; } 83926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 84040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenStringConstant)) { 84140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 84240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 84340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 84440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 84526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = struct_def.fields.Lookup(name); 84613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!field) { 84713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!opts.skip_unexpected_fields_in_json) { 84813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return Error("unknown field: " + name); 84913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 85013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 85113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 85213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 85313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 85413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 855049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (Is(kTokenNull)) { 856049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen NEXT(); // Ignore this field. 857049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } else { 858049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen Value val = field->value; 8599e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(val, field, fieldn, &struct_def)); 860049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // Hardcoded insertion-sort with error-check. 861049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // If fields are specified in order, then this loop exits immediately. 862eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto elem = field_stack_.rbegin(); 863eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (; elem != field_stack_.rbegin() + fieldn; ++elem) { 864eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto existing_field = elem->second; 865049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field == field) 866049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return Error("field set more than once: " + field->name); 867049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field->value.offset < field->value.offset) break; 868049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 869eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Note: elem points to before the insertion point, thus .base() points 870eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // to the correct spot. 871eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen field_stack_.insert(elem.base(), std::make_pair(val, field)); 872049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen fieldn++; 87313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 8744d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen } 87540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) { NEXT(); break; } 87640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 87726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 87813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 87926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && fieldn != struct_def.fields.vec.size()) 88040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("struct: wrong number of initializers: " + struct_def.name); 8814d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen 88226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 88326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 88426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 88526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 88626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 88726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 88826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 88926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 89026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = field_stack_.rbegin(); 89126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 892721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma auto &field_value = it->first; 89326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 89440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.sortbysize || 89540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen size == SizeOf(field_value.type.base_type)) { 896721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma switch (field_value.type.base_type) { 89748dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 89848dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 89926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 90026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 901be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 90240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 90340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 90440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(val); \ 905be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 90640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val, valdef; \ 90740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 90840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 90940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddElement(field_value.offset, val, valdef); \ 910be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 91126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 91226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 91326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 91448dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 91548dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 91626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 91726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 91826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 919721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma SerializeStruct(*field->value.type.struct_def, field_value); \ 92026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 92140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 92240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 92340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddOffset(field_value.offset, val); \ 92426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 92526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 92626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 92726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 92826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 92926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 93026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 93126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 93226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t i = 0; i < fieldn; i++) field_stack_.pop_back(); 93326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 93426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 93526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 93626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 9374d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(value); 9384d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // Temporarily store this struct in the value string, since it is to 9394d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // be serialized in-place elsewhere. 9404d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen value->assign( 9414d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 9424d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 94326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 94440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen assert(!ovalue); 94526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 94640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto val = builder_.EndTable(start, 94740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen static_cast<voffset_t>(struct_def.fields.vec.size())); 94840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (ovalue) *ovalue = val; 94940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (value) *value = NumToString(val); 95026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 95140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 95226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 95326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 95440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 95526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int count = 0; 9566c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 95740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((!opts.strict_json || !count) && Is(']')) { NEXT(); break; } 95826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 95926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.type = type; 9609e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(val, nullptr, 0, nullptr)); 96126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.push_back(std::make_pair(val, nullptr)); 96226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen count++; 96340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(']')) { NEXT(); break; } 96440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 96526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 967be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 968be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 96926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (int i = 0; i < count; i++) { 97026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 97126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 97226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 97348dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 97426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 97526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 97640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen else { \ 97740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE elem; \ 97840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 97940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(elem); \ 98040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } \ 98126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 98226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 98326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 98426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 98526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 98626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 98726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 98826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 98940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *ovalue = builder_.EndVector(count); 99040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 99126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 99226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 993e6b79f00022aee3108427977c9823ff57154e1c6Wouter van OortmerssenCheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 99440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('(')) { 99540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 99626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 99726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 99840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 9990952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen if (known_attributes_.find(name) == known_attributes_.end()) 100040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("user define attributes must be declared before use: " + 100140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen name); 100226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 1003e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen attributes->Add(name, e); 100440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(':')) { 100540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 100640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(*e)); 100726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 100840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(')')) { NEXT(); break; } 100940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 101026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 101126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 101240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 101326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 101426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 101540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e, 101640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BaseType req, bool *destmatch) { 101726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 101826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 101940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *destmatch = true; 102026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 102126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 102226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 102326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 102426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 102540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error(std::string("type mismatch: expecting: ") + 102640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[e.type.base_type] + 102740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ", found: " + 102840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[req]); 102926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 103226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 103426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 103526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1036fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van OortmerssenCheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 103740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result = 0; 10389c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 10399c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 10409c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 10419c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 10429c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 10439c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 10449c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 10459c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 10469c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 10479c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 10489c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 10499c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 10509c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 10519c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 10529c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 105340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown enum value: " + word + 10549c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 105540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 10569c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 10579c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 105840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("not a valid value for this field: " + word); 10599c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 106039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen const char *dot = strrchr(word.c_str(), '.'); 106140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!dot) 106240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values need to be qualified by an enum type"); 10639c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 10649c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 106539833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(enum_def_str); 106640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_def) return Error("unknown enum: " + enum_def_str); 10679c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 106840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("unknown enum value: " + enum_val_str); 106940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 10709c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 10719c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 107240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 10739c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 10749c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 1075d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 107640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHash(Value &e, FieldDef* field) { 1077d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(field); 1078d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames Value *hash_name = field->attributes.Lookup("hash"); 1079d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (e.type.base_type) { 1080d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 1081d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 1082d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction32(hash_name->constant.c_str()); 1083d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint32_t hashed_value = hash(attribute_.c_str()); 1084d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1085d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1086d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1087d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 1088d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 1089d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction64(hash_name->constant.c_str()); 1090d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint64_t hashed_value = hash(attribute_.c_str()); 1091d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1092d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1093d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1094d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 1095d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(0); 1096d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 109740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 109840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1099d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames} 1100d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 110140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseSingleValue(Value &e) { 1102d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // First see if this could be a conversion function: 1103d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (token_ == kTokenIdentifier && *cursor_ == '(') { 1104d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto functionname = attribute_; 1105d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen NEXT(); 1106d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT('('); 1107d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen ECHECK(ParseSingleValue(e)); 1108d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT(')'); 1109d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1110d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (functionname == name) { \ 1111d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto x = strtod(e.constant.c_str(), nullptr); \ 1112d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen e.constant = NumToString(op); \ 1113d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } 1114d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("deg", x / M_PI * 180); 1115d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("rad", x * M_PI / 180); 1116d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1117d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1118d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1119d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1120d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1121d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1122d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // TODO(wvo): add more useful conversion functions here. 1123d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #undef FLATBUFFERS_FN_DOUBLE 1124d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // Then check if this could be a string/identifier enum value: 1125d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } else if (e.type.base_type != BASE_TYPE_STRING && 11269c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 11279c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 1128fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(attribute_[0])) { // Enum value. 1129fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen int64_t val; 1130fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen ECHECK(ParseEnumFromString(e.type, &val)); 1131fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(val); 1132fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen NEXT(); 1133fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { // Numeric constant in string. 1134fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsInteger(e.type.base_type)) { 1135b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1136b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(StringToInt(attribute_.c_str(), &end)); 1137b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1138b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid integer: " + attribute_); 1139fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else if (IsFloat(e.type.base_type)) { 1140b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1141b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(strtod(attribute_.c_str(), &end)); 1142b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1143b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid float: " + attribute_); 1144fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { 1145fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen assert(0); // Shouldn't happen, we covered all types. 1146fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = "0"; 1147fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 114883dc5ed4a7267c78fb3f00e972de4db30762166dWouter van Oortmerssen NEXT(); 1149fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 115026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 115140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool match = false; 115240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenIntegerConstant, 115340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(e.type.base_type), 115440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 115540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_INT, 115640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 115740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenFloatConstant, 115840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsFloat(e.type.base_type), 115940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 116040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_FLOAT, 116140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 116240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenStringConstant, 116340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 116440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 116540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_STRING, 116640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 116740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!match) 116840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot parse value starting with: " + 116940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 117026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 117140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 117226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 117326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 117494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name, 117594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool create_if_new, bool definition) { 117694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string qualified_name = namespaces_.back()->GetFullyQualifiedName(name); 117720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an unqualified use. 117894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto struct_def = structs_.Lookup(name); 117994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 118094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 118120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace, and is registered under its 118220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // qualified name. 118394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 118494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Move(name, qualified_name); 118594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 118694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return struct_def; 118794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 118820c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an qualified use. 118994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup(qualified_name); 119020c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 119120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (definition) { 119220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace. 119320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 119420c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 119520c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen return struct_def; 119620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 119794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!definition) { 119894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 119994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t components = namespaces_.back()->components.size(); 120094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components && !struct_def; components--) { 120194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup( 120294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name, components - 1)); 120394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 120494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 120594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!struct_def && create_if_new) { 120626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 120794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 120894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(qualified_name, struct_def); 120994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 121094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 121194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 121294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Not a definition. 121394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 121494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 121594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // It is defined in the root namespace, since we don't know what the 121694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // final namespace will be. 121794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: maybe safer to use special namespace? 121894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(name, struct_def); 121994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 122094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = new Namespace(); 122194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), struct_def->defined_namespace); 122294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 122326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 122426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 122526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 122626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 122740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1228c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::vector<std::string> enum_comment = doc_comment_; 122940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1230c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::string enum_name = attribute_; 123140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 123226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 1233c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.name = enum_name; 123440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen enum_def.file = file_being_parsed_; 1235c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.doc_comment = enum_comment; 123626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 12377b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen enum_def.defined_namespace = namespaces_.back(); 123894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enums_.Add(namespaces_.back()->GetFullyQualifiedName(enum_name), 123994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen &enum_def)) 124040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum already exists: " + enum_name); 124126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 124226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 124326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 1244a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 124545bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode) { 124694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_INT; 1247d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 1248d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Give specialized error message, since this type spec used to 1249d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // be optional in the first FlatBuffers release. 125040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(':')) { 125140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("must specify the underlying integer type for this" 125240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 125340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 125440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 125540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 1256d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Specify the integer type underlying this enum. 125740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(enum_def.underlying_type)); 1258d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 125940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("underlying enum type must be integral"); 1260d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 12613fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 12623fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 126326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1264e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&enum_def.attributes)); 126540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 126626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 126740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 126845bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode && attribute_ == "option") { 126940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 127094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 127194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value_name = attribute_; 127294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto full_name = value_name; 127394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> value_comment = doc_comment_; 127440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 12753639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen if (is_union) { 12763639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen ECHECK(ParseNamespacing(&full_name, &value_name)); 1277d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen if (opts.union_value_namespacing) { 1278d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // Since we can't namespace the actual enum identifiers, turn 1279d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // namespace parts into part of the identifier. 1280d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen value_name = full_name; 1281d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen std::replace(value_name.begin(), value_name.end(), '.', '_'); 1282d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen } 12833639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen } 128494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 128594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value = enum_def.vals.vec.size() 128694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 128794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen : 0; 128894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &ev = *new EnumVal(value_name, value); 128994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enum_def.vals.Add(value_name, &ev)) 129040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum value already exists: " + value_name); 129194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.doc_comment = value_comment; 129294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (is_union) { 129394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.struct_def = LookupCreateStruct(full_name); 129494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 129540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('=')) { 129640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1297d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen ev.value = StringToInt(attribute_.c_str()); 129840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 129945bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (!opts.proto_mode && prevsize && 130094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.vals.vec[prevsize - 1]->value >= ev.value) 130140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values must be specified in ascending order"); 130294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 130340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && Is('[')) { 130440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 130594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // ignore attributes on enums. 130640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != ']') NEXT(); 130740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 130894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 130926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 131040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(opts.proto_mode ? ';' : ',')) break; 131140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 131240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) break; 131340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 131440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1315127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 1316127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1317127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 1318127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 1319127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 132040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("bit flag out of range of underlying integral type"); 13219c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 1322127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 1323127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 132440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (dest) *dest = &enum_def; 13259b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen types_.Add(namespaces_.back()->GetFullyQualifiedName(enum_def.name), 13269b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_UNION, nullptr, &enum_def)); 132740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 132826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 132926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 133040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 133194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name, true, true); 133240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.predecl) return Error("datatype already exists: " + name); 133326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 133426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 133540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def.file = file_being_parsed_; 133626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 1337d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // to preserve declaration order. 13383b070310f03326597666babf6654aa983d063bb2Wouter van Oortmerssen *remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; 133940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &struct_def; 134040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1341d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1342d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1343b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra PenkeCheckedError Parser::CheckClash(std::vector<FieldDef*> &fields, 1344b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke StructDef *struct_def, 1345b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke const char *suffix, 1346b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke BaseType basetype) { 1347b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto len = strlen(suffix); 1348b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke for (auto it = fields.begin(); it != fields.end(); ++it) { 1349b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto &fname = (*it)->name; 1350b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (fname.length() > len && 1351b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.compare(fname.length() - len, len, suffix) == 0 && 1352b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1353b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto field = struct_def->fields.Lookup( 1354b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.substr(0, fname.length() - len)); 1355b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (field && field->value.type.base_type == basetype) 1356b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return Error("Field " + fname + 1357b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke " would clash with generated functions for field " + 1358b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke field->name); 1359b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1360b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1361b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return NoError(); 1362b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1363d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen 1364b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1365b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1366b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1367b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a_id < b_id; 1368b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1369b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 137040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseDecl() { 1371d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen std::vector<std::string> dc = doc_comment_; 137240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool fixed = Is(kTokenStruct); 137340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (fixed) NEXT() else EXPECT(kTokenTable); 137494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 137540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 137640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StructDef *struct_def; 137740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 137840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->doc_comment = dc; 137940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->fixed = fixed; 1380e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&struct_def->attributes)); 138140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->sortbysize = 138240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 138340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 138440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != '}') ECHECK(ParseField(*struct_def)); 138540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto force_align = struct_def->attributes.Lookup("force_align"); 138626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 138726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 138826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 138940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen align < struct_def->minalign || 13906862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen align > FLATBUFFERS_MAX_ALIGNMENT || 139126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 139240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("force_align must be a power of two integer ranging from the" 13936862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen "struct\'s natural alignment to " + 13946862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen NumToString(FLATBUFFERS_MAX_ALIGNMENT)); 139540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->minalign = align; 139626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 139740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->PadLastField(struct_def->minalign); 13989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 139940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &fields = struct_def->fields.vec; 140040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def->fixed && fields.size()) { 14017fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 14029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 14039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 14049140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 14059140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 14069140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 14079140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 14089140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 140940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 141040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "either all fields or no fields must have an 'id' attribute"); 14119140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 14129140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 1413b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(fields.begin(), fields.end(), compareFieldDefs); 14149140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 14159140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 14169140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 141740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field id\'s must be consecutive from 0, id " + 14189140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 14199140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 14209140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 14219140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 14229140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 1423b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 14249e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), 14259e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen BASE_TYPE_UNION)); 1426b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1427b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1428b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1429b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1430b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 143140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 14329b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen types_.Add(namespaces_.back()->GetFullyQualifiedName(struct_def->name), 14339b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_STRUCT, struct_def, nullptr)); 143440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 143526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 143626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14371a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van OortmerssenCheckedError Parser::ParseService() { 14381a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen std::vector<std::string> service_comment = doc_comment_; 14391a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 14401a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto service_name = attribute_; 14411a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14421a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &service_def = *new ServiceDef(); 14431a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.name = service_name; 14441a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.file = file_being_parsed_; 14451a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.doc_comment = service_comment; 14461a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.defined_namespace = namespaces_.back(); 14471a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (services_.Add(namespaces_.back()->GetFullyQualifiedName(service_name), 14481a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen &service_def)) 14491a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("service already exists: " + service_name); 1450e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&service_def.attributes)); 14511a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('{'); 14521a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen do { 14531a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto rpc_name = attribute_; 14541a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14551a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('('); 14561a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen Type reqtype, resptype; 14571a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(reqtype)); 14581a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(')'); 14591a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(':'); 14601a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(resptype)); 14611a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 14621a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 14631a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc request and response types must be tables"); 14641a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &rpc = *new RPCCall(); 14651a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.name = rpc_name; 14661a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.request = reqtype.struct_def; 14671a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.response = resptype.struct_def; 14681a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (service_def.calls.Add(rpc_name, &rpc)) 14691a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc already exists: " + rpc_name); 1470e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&rpc.attributes)); 14711a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(';'); 14721a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } while (token_ != '}'); 14731a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 14741a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 14751a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen} 14761a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen 147726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 14784dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup(name); 14794dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen if (!root_struct_def_) 14804dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup( 14814dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name)); 148281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return root_struct_def_ != nullptr; 148326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 148426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1485be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 14863881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // This function marks all existing definitions as having already 14873881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // been generated, which signals no code for included files should be 14883881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // generated. 1489be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 1490be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 1491be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1492be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 1493be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 1494be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 1495be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1496be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 149748f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen for (auto it = services_.vec.begin(); 149848f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen it != services_.vec.end(); ++it) { 149948f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen (*it)->generated = true; 150048f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen } 1501be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 1502be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 150340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespace() { 150440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1505d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen auto ns = new Namespace(); 1506d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen namespaces_.push_back(ns); 150794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ != ';') { 150894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (;;) { 150994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(attribute_); 151040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 151140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT() else break; 151294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1513d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 151440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 151540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1516d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1517d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1518b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareEnumVals(const EnumVal *a, const EnumVal* b) { 1519b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a->value < b->value; 1520b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1521b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 1522d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Best effort parsing of .proto declarations, with the aim to turn them 1523d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// in the closest corresponding FlatBuffer equivalent. 1524d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// We parse everything as identifiers instead of keywords, since we don't 1525d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// want protobuf keywords to become invalid identifiers in FlatBuffers. 152640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoDecl() { 152794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool isextend = attribute_ == "extend"; 1528d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == "package") { 1529d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // These are identical in syntax to FlatBuffer's namespace decl. 153040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 153194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "message" || isextend) { 15323ad853630c6bf76a9c8fc2a15e3fc40cd52de691Advay Mengle std::vector<std::string> struct_comment = doc_comment_; 153340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 153494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *struct_def = nullptr; 153594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 153640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 153794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto id = attribute_; 153840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 153940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 154094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = LookupCreateStruct(id, false); 154140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def) 154240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot extend unknown message type: " + id); 154394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 154494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 154540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 154640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 154794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Since message definitions can be nested, we create a new namespace. 154894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = new Namespace(); 154994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Copy of current namespace. 155094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen *ns = *namespaces_.back(); 155194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // But with current message name. 155294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(name); 155394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(ns); 155494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 155594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->doc_comment = struct_comment; 155640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(struct_def, isextend, false)); 155794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!isextend) { 155894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We have to remove the nested namespace, but we can't just throw it 155994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // away, so put it at the beginning of the vector. 156094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = namespaces_.back(); 156194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.pop_back(); 156294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), ns); 156394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 156440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 156594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "enum") { 156694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // These are almost the same, just with different terminator: 156740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EnumDef *enum_def; 156840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, &enum_def)); 156940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 157094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protobuf allows them to be specified in any order, so sort afterwards. 157140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &v = enum_def->vals.vec; 1572d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen std::sort(v.begin(), v.end(), compareEnumVals); 1573b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 157494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: remove any duplicates, as .fbs files can't handle them. 157594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (auto it = v.begin(); it != v.end(); ) { 157694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it); 157794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else ++it; 157894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 157994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "syntax") { // Skip these. 158040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 158140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 158240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 158340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 158494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 158540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 158640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 158794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "service") { // Skip these. 158840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 158940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 159040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 159194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 159240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("don\'t know how to parse .proto declaration starting with " + 159394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen TokenToStringId(token_)); 159494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 159540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 159694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 159794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 159840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 159940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool inside_oneof) { 160040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 160194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (token_ != '}') { 160294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "message" || attribute_ == "extend" || 160394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_ == "enum") { 160494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Nested declarations. 160540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 160694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "extensions") { // Skip these. 160740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 160840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 160940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenIdentifier)) { 161040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // to 161140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // num 161294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 161340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 161494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 161540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 161640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 161794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "reserved") { // Skip these. 161840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 161940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 162040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } 162140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 162294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 162394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> field_comment = doc_comment_; 162494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Parse the qualifier. 162594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool required = false; 162694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool repeated = false; 162794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool oneof = false; 162894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!inside_oneof) { 16292abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen if (attribute_ == "optional") { 16302abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // This is the default. 163140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16322abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "required") { 16332abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen required = true; 163440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16352abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "repeated") { 16362abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen repeated = true; 163740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 163894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "oneof") { 163994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen oneof = true; 164040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16412abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else { 164294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // can't error, proto3 allows decls without any of the above. 16432abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } 164494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 164594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *anonymous_struct = nullptr; 164694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen Type type; 164794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "group" || oneof) { 164840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!oneof) EXPECT(kTokenIdentifier); 164994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto name = "Anonymous" + NumToString(anonymous_counter++); 165040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &anonymous_struct)); 165194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type = Type(BASE_TYPE_STRUCT, anonymous_struct); 165294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 165340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeFromProtoType(&type)); 165494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 165594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Repeated elements get mapped to a vector. 165694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (repeated) { 165794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.element = type.base_type; 165894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.base_type = BASE_TYPE_VECTOR; 165994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 166094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 166194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protos may use our keywords "attribute" & "namespace" as an identifier. 166240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenAttribute) || Is(kTokenNameSpace)) { 166340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 166494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: simpler to just not make these keywords? 166594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen name += "_"; // Have to make it not a keyword. 166694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 166740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 166894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 166994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!oneof) { 16702abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // Parse the field id. Since we're just translating schemas, not 16712abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // any kind of binary compatibility, we can safely ignore these, and 16722abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // assign our own. 167340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 167440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 167594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 167640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field = nullptr; 167794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 167894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We allow a field to be re-defined when extending. 167994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: are there situations where that is problematic? 168040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field = struct_def->fields.Lookup(name); 168194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 168240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 168340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = field_comment; 168440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(type.base_type)) field->required = required; 168594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // See if there's a default specified. 168640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('[')) { 168740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 168840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 168994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto key = attribute_; 169040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 169140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 169294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto val = attribute_; 169340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 169494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (key == "default") { 169594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: skip non-numeric defaults (enums). 169694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto numeric = strpbrk(val.c_str(), "0123456789-+."); 169794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (IsScalar(type.base_type) && numeric == val.c_str()) 169840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant = val; 169994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (key == "deprecated") { 170040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = val == "true"; 170194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 170240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(',')) break; 170340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 170440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 170540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 170694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 170794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (anonymous_struct) { 170840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 170940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 171094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 171140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 1712d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1713d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 171494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 171540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 171640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 171794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 171894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 171940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoKey() { 172094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '(') { 172140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 172294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Skip "(a.b)" style custom attributes. 172340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 172440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(')'); 172540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { NEXT(); EXPECT(kTokenIdentifier); } 172694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 172740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 172894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 172940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 173094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 173194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 173240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoCurliesOrIdent() { 173340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('{')) { 173440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 173594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int nesting = 1; nesting; ) { 173694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '{') nesting++; 173794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else if (token_ == '}') nesting--; 173840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 173994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1740d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 174140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // Any single token. 1742d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 174340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1744d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1745d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 174640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoOption() { 174740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 174840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 174940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 175040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 175140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 175294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 175394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 1754d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Parse a protobuf type, and map it to the corresponding FlatBuffer one. 175540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeFromProtoType(Type *type) { 1756d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen struct type_lookup { const char *proto_type; BaseType fb_type; }; 1757d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen static type_lookup lookup[] = { 1758d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "float", BASE_TYPE_FLOAT }, { "double", BASE_TYPE_DOUBLE }, 1759d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "int32", BASE_TYPE_INT }, { "int64", BASE_TYPE_LONG }, 1760d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "uint32", BASE_TYPE_UINT }, { "uint64", BASE_TYPE_ULONG }, 1761d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sint32", BASE_TYPE_INT }, { "sint64", BASE_TYPE_LONG }, 1762d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "fixed32", BASE_TYPE_UINT }, { "fixed64", BASE_TYPE_ULONG }, 1763d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sfixed32", BASE_TYPE_INT }, { "sfixed64", BASE_TYPE_LONG }, 1764d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bool", BASE_TYPE_BOOL }, 1765d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "string", BASE_TYPE_STRING }, 1766d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bytes", BASE_TYPE_STRING }, 1767d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { nullptr, BASE_TYPE_NONE } 1768d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen }; 1769d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen for (auto tl = lookup; tl->proto_type; tl++) { 1770d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == tl->proto_type) { 177140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen type->base_type = tl->fb_type; 177240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 177340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1774d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1775d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 177640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 177740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(*type)); 177840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1779d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1780d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 178113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipAnyJsonValue() { 178213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke switch (token_) { 178313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case '{': 178413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonObject()); 178513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 178613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenStringConstant: 178713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonString()); 178813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 178913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case '[': 179013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonArray()); 179113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 179213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenIntegerConstant: 179313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenIntegerConstant); 179413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 179513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenFloatConstant: 179613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenFloatConstant); 179713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 179813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke default: 1799e0b2f81885b09ffba4ec89bfd2c9796d3be01865Chris Pickett return Error(std::string("Unexpected token:") + std::string(1, static_cast<char>(token_))); 180013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 180113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 180213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 180313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 180413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonObject() { 180513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT('{'); 180613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke size_t fieldn = 0; 180713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 18080e1601b80de3c69cf49894d58840856f2077731bChris Pickett for (;;) { 180913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if ((!opts.strict_json || !fieldn) && Is('}')) break; 181013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 1811cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke if (!Is(kTokenStringConstant)) { 181213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 1813cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 1814cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke else { 1815cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke NEXT(); 1816cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 181713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 181813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 181913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 182013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke fieldn++; 182113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 182213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is('}')) break; 182313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(','); 182413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 182513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 182613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke NEXT(); 182713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 182813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 182913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 183013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonArray() { 183113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT('['); 1832049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen 18330e1601b80de3c69cf49894d58840856f2077731bChris Pickett for (;;) { 183413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is(']')) break; 1835049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen 183613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 183713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 183813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is(']')) break; 183913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(','); 184013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 184113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 184213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke NEXT(); 184313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 184413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 184513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 184613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonString() { 184713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenStringConstant); 184813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 184913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 185013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 185130642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths, 185230642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen const char *source_filename) { 185340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return !DoParse(source, include_paths, source_filename).Check(); 185440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen} 185540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 185640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::DoParse(const char *source, const char **include_paths, 185740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const char *source_filename) { 185840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_being_parsed_ = source_filename ? source_filename : ""; 1859df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (source_filename && 1860df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files_.find(source_filename) == included_files_.end()) { 1861df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files_[source_filename] = true; 1862df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez files_included_per_file_[source_filename] = std::set<std::string>(); 1863df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 1864df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (!include_paths) { 18651e6f8f5b8c4d0407d7db750858e7863e07091958Wouter van Oortmerssen static const char *current_directory[] = { "", nullptr }; 1866df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez include_paths = current_directory; 1867df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 186826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen source_ = cursor_ = source; 186926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen line_ = 1; 187026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen error_.clear(); 1871fea6b525ee57bf61d307abc16ade8d9041a3a01dYonggang Li field_stack_.clear(); 187226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 187394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Start with a blank namespace just in case this file doesn't have one. 187494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(new Namespace()); 1875cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli ECHECK(SkipByteOrderMark()); 187640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 187740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Includes must come before type declarations: 187840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 187940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Parse pre-include proto statements if any: 188040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && 188140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (attribute_ == "option" || attribute_ == "syntax" || 188240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "package")) { 188340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 18843f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen } else if (Is(kTokenNativeInclude)) { 18853f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen NEXT(); 18863f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen native_included_files_.emplace_back(attribute_); 18873f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen EXPECT(kTokenStringConstant); 188840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (Is(kTokenInclude) || 188940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (opts.proto_mode && 189040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "import" && 189140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Is(kTokenIdentifier))) { 189240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 189340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && attribute_ == "public") NEXT(); 189440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 189540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 189640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Look for the file in include_paths. 189740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string filepath; 189840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 189940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen filepath = flatbuffers::ConCatPathFileName(*paths, name); 190040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if(FileExists(filepath.c_str())) break; 1901be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 190240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (filepath.empty()) 190340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to locate include file: " + name); 190440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (source_filename) 190540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen files_included_per_file_[source_filename].insert(filepath); 190640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (included_files_.find(filepath) == included_files_.end()) { 190740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We found an include file that we have not parsed yet. 190840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Load it and parse it. 190940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string contents; 191040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!LoadFile(filepath.c_str(), true, &contents)) 191140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to load include file: " + name); 191240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str())); 191340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We generally do not want to output code for any included files: 191440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!opts.generate_all) MarkGenerated(); 191540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is the easiest way to continue this file after an include: 191640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 191740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // file anew. This will cause it to encounter the same include 191840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statement again, but this time it will skip it, because it was 191940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // entered into included_files_. 192040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is recursive, but only go as deep as the number of include 192140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statements. 192240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return DoParse(source, include_paths, source_filename); 192326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 192440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 192540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 192640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen break; 192726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 192840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 192940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Now parse all other kinds of declarations: 193040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != kTokenEof) { 193140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode) { 193240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 193340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenNameSpace) { 193440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 193540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == '{') { 193640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!root_struct_def_) 193740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("no root type set to parse json with"); 193840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (builder_.GetSize()) { 193940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot have more than one json object in a file"); 194094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 194140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t toff; 194240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 194340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.Finish(Offset<Table>(toff), 194440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 194540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenEnum) { 194640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, nullptr)); 194740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenUnion) { 194840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(true, nullptr)); 194940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenRootType) { 195040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 195140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto root_type = attribute_; 195240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 195340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&root_type, nullptr)); 195440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 195540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown root type: " + root_type); 195640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (root_struct_def_->fixed) 195740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("root type must be a table"); 195840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 195940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileIdentifier) { 196040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 196140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_ = attribute_; 196240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 196340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_identifier_.length() != 196440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 196540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("file_identifier must be exactly " + 196640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 196740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " characters"); 196840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 196940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileExtension) { 197040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 197140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_extension_ = attribute_; 197240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 197340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 197440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenInclude) { 197540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("includes must come before declarations"); 197640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenAttribute) { 197740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 197840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 197940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 198040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 198172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen known_attributes_[name] = false; 19821a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } else if (token_ == kTokenService) { 19831a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseService()); 198440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 198540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseDecl()); 198626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 198740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 198840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 198940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((*it)->predecl) { 199040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("type referenced but not defined: " + (*it)->name); 199140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 199240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 199340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 199440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &enum_def = **it; 199540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (enum_def.is_union) { 199640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto val_it = enum_def.vals.vec.begin(); 199740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val_it != enum_def.vals.vec.end(); 199840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ++val_it) { 199940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &val = **val_it; 200040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (val.struct_def && val.struct_def->fixed) 200140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only tables can be union elements: " + val.name); 200226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 200326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 200426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 200540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 200626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 200726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2008df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinezstd::set<std::string> Parser::GetIncludedFilesRecursive( 2009df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez const std::string &file_name) const { 2010df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::set<std::string> included_files; 2011df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::list<std::string> to_process; 2012df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2013df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (file_name.empty()) return included_files; 2014df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(file_name); 2015df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2016df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez while (!to_process.empty()) { 2017df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::string current = to_process.front(); 2018df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.pop_front(); 2019df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files.insert(current); 2020df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2021df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez auto new_files = files_included_per_file_.at(current); 2022df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez for (auto it = new_files.begin(); it != new_files.end(); ++it) { 2023df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (included_files.find(*it) == included_files.end()) 2024df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(*it); 2025df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2026df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2027df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2028df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez return included_files; 2029df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez} 2030df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 203181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Schema serialization functionality: 203281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 2033b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penketemplate<typename T> bool compareName(const T* a, const T* b) { 2034df0991b7ded0533554d3665e782273b6c8736376Xun Liu return a->defined_namespace->GetFullyQualifiedName(a->name) 2035df0991b7ded0533554d3665e782273b6c8736376Xun Liu < b->defined_namespace->GetFullyQualifiedName(b->name); 2036b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 2037b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 203881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssentemplate<typename T> void AssignIndices(const std::vector<T *> &defvec) { 203981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // Pre-sort these vectors, such that we can set the correct indices for them. 204081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto vec = defvec; 2041b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(vec.begin(), vec.end(), compareName<T>); 204281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 204381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 204481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 204581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenvoid Parser::Serialize() { 204681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Clear(); 204781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(structs_.vec); 204881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(enums_.vec); 204981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Object>> object_offsets; 205081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 205172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 205281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen object_offsets.push_back(offset); 205381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 205481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 205581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Enum>> enum_offsets; 205681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 205772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 205881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enum_offsets.push_back(offset); 205981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 206081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 206181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto schema_offset = reflection::CreateSchema( 206281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_, 206381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&object_offsets), 206481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&enum_offsets), 206581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_identifier_), 206681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_extension_), 206736c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen root_struct_def_ 206836c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen ? root_struct_def_->serialized_location 206936c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen : 0); 207081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 207181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 207281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 207372fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 207472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 207581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Field>> field_offsets; 207681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2077622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen field_offsets.push_back( 2078622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen (*it)->Serialize(builder, 207972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<uint16_t>(it - fields.vec.begin()), parser)); 208081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2081df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 208281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateObject(*builder, 2083df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 208481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVectorOfSortedTables( 208581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen &field_offsets), 2086cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen fixed, 2087cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen static_cast<int>(minalign), 208872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<int>(bytesize), 208972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 209081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 209181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 209281312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 209372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen uint16_t id, 209472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 209581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateField(*builder, 209681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 209781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.type.Serialize(builder), 209881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen id, 209981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.offset, 210081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsInteger(value.type.base_type) 210181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? StringToInt(value.constant.c_str()) 210281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0, 210381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsFloat(value.type.base_type) 210481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? strtod(value.constant.c_str(), nullptr) 210581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0.0, 210681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen deprecated, 210781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen required, 210872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen key, 210972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 211081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // TODO: value.constant is almost always "0", we could save quite a bit of 211181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // space by sharing it. Same for common values of value.type. 211281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 211381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 211472fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 211572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 211681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::EnumVal>> enumval_offsets; 211781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 211881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enumval_offsets.push_back((*it)->Serialize(builder)); 211981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2120df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 212181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnum(*builder, 2122df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 212381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVector(enumval_offsets), 212481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen is_union, 212572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen underlying_type.Serialize(builder), 212672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 212781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 212881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 212981312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const 213081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen { 213181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnumVal(*builder, 213281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 213381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value, 213481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def 213581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? struct_def->serialized_location 213681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0); 213781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 213881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 213981312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 214081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateType(*builder, 214181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(base_type), 214281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(element), 214381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def ? struct_def->index : 214481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (enum_def ? enum_def->index : -1)); 214581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 214681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 214772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssenflatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< 214872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen reflection::KeyValue>>> 214972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen Definition::SerializeAttributes(FlatBufferBuilder *builder, 215072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 215172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2152e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 2153e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen auto it = parser.known_attributes_.find(kv->first); 215472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen assert(it != parser.known_attributes_.end()); 215572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (!it->second) { // Custom attribute. 215672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen attrs.push_back( 2157e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen reflection::CreateKeyValue(*builder, builder->CreateString(kv->first), 215872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen builder->CreateString( 2159e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen kv->second->constant))); 216072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 216172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 216272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (attrs.size()) { 216372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return builder->CreateVectorOfSortedTables(&attrs); 216472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } else { 216572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return 0; 216672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 216772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen} 216872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen 216905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssenstd::string Parser::ConformTo(const Parser &base) { 217005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 217105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &struct_def = **sit; 217205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 217305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 217405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto struct_def_base = base.structs_.Lookup(qualified_name); 217505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!struct_def_base) continue; 217605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fit = struct_def.fields.vec.begin(); 217705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fit != struct_def.fields.vec.end(); ++fit) { 217805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &field = **fit; 217905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto field_base = struct_def_base->fields.Lookup(field.name); 218005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field_base) { 218105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset != field_base->value.offset) 218205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "offsets differ for field: " + field.name; 218305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.constant != field_base->value.constant) 218405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "defaults differ for field: " + field.name; 218505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 218605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "types differ for field: " + field.name; 218705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } else { 218805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // Doesn't have to exist, deleting fields is fine. 218905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // But we should check if there is a field that has the same offset 219005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // but is incompatible (in the case of field renaming). 219105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fbit = struct_def_base->fields.vec.begin(); 219205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fbit != struct_def_base->fields.vec.end(); ++fbit) { 219305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen field_base = *fbit; 219405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset == field_base->value.offset) { 219505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 219605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "field renamed to different type: " + field.name; 219705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen break; 219805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 219905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 220005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 220105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 220205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 220305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 220405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_def = **eit; 220505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 220605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 220705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_def_base = base.enums_.Lookup(qualified_name); 220805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!enum_def_base) continue; 220905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto evit = enum_def.vals.vec.begin(); 221005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen evit != enum_def.vals.vec.end(); ++evit) { 221105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_val = **evit; 221205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 221305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val_base) { 221405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val.value != enum_val_base->value) 221505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "values differ for enum: " + enum_val.name; 221605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 221705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 221805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 221905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return ""; 222005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen} 222105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen 222226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 2223