idl_parser.cpp revision 2e2063cbeb6ea95c804796c443153f71797c3629
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 89a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbsinline std::string OutOfRangeErrorMsg(int64_t val, const std::string &op, 90a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs int64_t limit) { 91a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs const std::string cause = NumToString(val) + op + NumToString(limit); 92a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return "constant does not fit (" + cause + ")"; 93a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs} 94a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs 9526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 96a07f0d428d1175ae52b2f91357f535927c9d6287Jason StubbsCheckedError Parser::CheckInRange(int64_t val, int64_t min, int64_t max) { 97a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs if (val < min) 98a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " < ", min)); 99a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else if (val > max) 100a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " > ", max)); 101a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else 102a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return NoError(); 10326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 10426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 10640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<typename T> inline CheckedError atot(const char *s, Parser &parser, 10740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen T *val) { 10840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t i = StringToInt(s); 109a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs const int64_t min = std::numeric_limits<T>::min(); 110a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs const int64_t max = std::numeric_limits<T>::max(); 111a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs ECHECK(parser.CheckInRange(i, min, max)); 11240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = (T)i; 11340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11529574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssentemplate<> inline CheckedError atot<uint64_t>(const char *s, Parser &parser, 11629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t *val) { 11729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (void)parser; 11829574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen *val = StringToUInt(s); 11929574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen return NoError(); 12029574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen} 12140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<bool>(const char *s, Parser &parser, 12240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool *val) { 12340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = 0 != atoi(s); 12540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 12740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<float>(const char *s, Parser &parser, 12840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen float *val) { 12940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = static_cast<float>(strtod(s, nullptr)); 13140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<double>(const char *s, Parser &parser, 13440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen double *val) { 13540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = strtod(s, nullptr); 13740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 14140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Offset<void> *val) { 14240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 14340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = Offset<void>(atoi(s)); 14440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 14526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Namespace::GetFullyQualifiedName(const std::string &name, 14894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen size_t max_components) const { 14994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Early exit if we don't have a defined namespace. 15094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (components.size() == 0 || !max_components) { 15194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return name; 15294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::stringstream stream; 15494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t i = 0; i < std::min(components.size(), max_components); 15594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen i++) { 15694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (i) { 15794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "."; 15894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << components[i]; 16094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1618c1a723ba55d1574590eba801d64afab9c49e017Wouter van Oortmerssen if (name.length()) stream << "." << name; 16294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return stream.str(); 16394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 16494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 16826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 16926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 17026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 17126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 17226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Identifier, 260, "identifier") \ 17526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Table, 261, "table") \ 17626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Struct, 262, "struct") \ 17726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Enum, 263, "enum") \ 17826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Union, 264, "union") \ 17926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(NameSpace, 265, "namespace") \ 1805da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(RootType, 266, "root_type") \ 1815da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(FileIdentifier, 267, "file_identifier") \ 182be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen TD(FileExtension, 268, "file_extension") \ 1830952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen TD(Include, 269, "include") \ 184049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen TD(Attribute, 270, "attribute") \ 1851a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen TD(Null, 271, "null") \ 1863f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen TD(Service, 272, "rpc_service") \ 1873f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen TD(NativeInclude, 273, "native_include") 1888f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 1898f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 1908f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 19275349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 19548dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 196557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen kToken ## ENUM, 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 19826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 20426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 20526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 20648dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 20748dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 20926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 21026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 21126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 21226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 2138e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 21426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 21526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 21626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 21726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 21826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 21926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 22094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Parser::TokenToStringId(int t) { 22194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return TokenToString(t) + (t == kTokenIdentifier ? ": " + attribute_ : ""); 22294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 22394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 224ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 22529574282a283ddc7904d096d27b783b794da7e91Wouter van OortmerssenCheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) { 226ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 22730013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if (!isxdigit(static_cast<const unsigned char>(cursor_[i]))) 22840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("escape code must be followed by " + NumToString(nibbles) + 22940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " hex digits"); 2307cf74cb8644262f8ca02d69705bbc394d66514ceHiroshi Matsunaga std::string target(cursor_, cursor_ + nibbles); 231b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain *val = StringToUInt(target.c_str(), nullptr, 16); 232ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 23340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 234ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 235ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 236cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <OliCheckedError Parser::SkipByteOrderMark() { 237cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError(); 238cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli cursor_++; 239f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbb) return Error("invalid utf-8 byte order mark"); 240f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 241f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbf) return Error("invalid utf-8 byte order mark"); 242f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 243cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli return NoError(); 244cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli} 245cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli 246fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssenbool IsIdentifierStart(char c) { 247fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen return isalpha(static_cast<unsigned char>(c)) || c == '_'; 248fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen} 249fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen 25040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Next() { 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 25226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 25394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.clear(); 25426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 25526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 25626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 25726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 25840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return NoError(); 25926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 26026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 26140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': 26240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case ',': case ':': case ';': case '=': return NoError(); 26326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 26430013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError(); 26540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("floating point constant can\'t start with \".\""); 26626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 2676704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield case '\'': { 2686704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int unicode_high_surrogate = -1; 2696704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield 27094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != c) { 27126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 27240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character in string constant"); 27326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 27426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 2756704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1 && 2766704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield *cursor_ != 'u') { 2776704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2786704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 2796704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 28026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 28126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 28226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 28326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 284ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 285ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 28626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 28794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen case '\'': attribute_ += '\''; cursor_++; break; 28826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 289ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 290ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 291ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 29229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 29340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(2, &val)); 29440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ += static_cast<char>(val); 295ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 296ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 297ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 298ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 29929574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 30040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(4, &val)); 3016704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (val >= 0xD800 && val <= 0xDBFF) { 3026704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3036704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3046704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (multiple high surrogates)"); 3056704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 306e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen unicode_high_surrogate = static_cast<int>(val); 3076704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3086704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else if (val >= 0xDC00 && val <= 0xDFFF) { 3096704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate == -1) { 3106704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3116704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired low surrogate)"); 3126704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3136704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int code_point = 0x10000 + 3146704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ((unicode_high_surrogate & 0x03FF) << 10) + 3156704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield (val & 0x03FF); 3166704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(code_point, &attribute_); 3176704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield unicode_high_surrogate = -1; 3186704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3196704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3206704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3216704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3226704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3236704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3246704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(static_cast<int>(val), &attribute_); 3256704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 326ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 327ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 32840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen default: return Error("unknown escape code in string constant"); 32926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 33026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 3316704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3326704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3336704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3346704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 33626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 33726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3386704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3396704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3406704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3416704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 34226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 343f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) { 344f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return Error("illegal UTF-8 sequence"); 345f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 34626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 34740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 3486704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 34926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 35026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 35126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 352a8d6962ac2fbf5075ee5f58877d488eb74ed32dfMormegil while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 35326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 35407d5965c812fa5e82dc4d3eb32b37540b7c91598Zbigniew Mandziejewicz if (cursor_ != source_ && !seen_newline) 35540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 35640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "a documentation comment should be on a line on its own"); 357730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez doc_comment_.push_back(std::string(start + 1, cursor_)); 35826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 35926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 36094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (*cursor_ == '*') { 36194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 36294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: make nested. 36394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != '*' || cursor_[1] != '/') { 364ab51b030939e02e55cac6f9e779d8696013819a9Wouter van Oortmerssen if (*cursor_ == '\n') line_++; 36540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!*cursor_) return Error("end of file in comment"); 36694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 36794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 36894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_ += 2; 36994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen break; 37026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 37126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 37226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 373fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(c)) { 37426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 37526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 37626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 37726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 37826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 37926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 38026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // First, see if it is a type keyword from the table of types: 38148dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 38248dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 38326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == IDLTYPE) { \ 38426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kToken ## ENUM; \ 38540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); \ 38626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 38726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 38826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 38926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If it's a boolean constant keyword, turn those into integers, 39026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // which simplifies our logic downstream. 39126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "true" || attribute_ == "false") { 39226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ = NumToString(attribute_ == "true"); 39326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 39440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 39626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Check for declaration keywords: 39740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "table") { 39840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenTable; 39940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "struct") { 40240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenStruct; 40340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "enum") { 40640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenEnum; 40740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "union") { 41040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenUnion; 41140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "namespace") { 41440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenNameSpace; 41540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "root_type") { 41840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenRootType; 41940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 42040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 42140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "include") { 42240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenInclude; 42340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 42440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 42540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "attribute") { 42640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenAttribute; 42740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 42840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 4295da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_identifier") { 4305da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileIdentifier; 43140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4325da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 4335da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_extension") { 4345da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileExtension; 43540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4365da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 437049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (attribute_ == "null") { 438049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen token_ = kTokenNull; 439049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return NoError(); 440049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 4411a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (attribute_ == "rpc_service") { 4421a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen token_ = kTokenService; 4431a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 4441a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } 4453f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen if (attribute_ == "native_include") { 4463f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen token_ = kTokenNativeInclude; 4473f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen return NoError(); 4483f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen } 44926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If not, it is a user-defined identifier: 45026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 45140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 45226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 45326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 45429574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen if (c == '-' && *cursor_ == '0' && 45529574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (cursor_[1] == 'x' || cursor_[1] == 'X')) { 456f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++start; 457f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++cursor_; 458f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman attribute_.append(&c, &c + 1); 459f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman c = '0'; 460f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman } 46194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { 46294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 46394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 46494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.append(start + 2, cursor_); 46529574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen attribute_ = NumToString(static_cast<int64_t>( 46629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen StringToUInt(attribute_.c_str(), nullptr, 16))); 46794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen token_ = kTokenIntegerConstant; 46840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 46994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 47026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 47194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.' || *cursor_ == 'e' || *cursor_ == 'E') { 47294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.') { 47394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 47494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 47594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 47693df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 47793df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 47893df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 47993df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 48093df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 48193df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 48293df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 48326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 48426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 48526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 48626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 48726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 48840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 48926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 49126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 49226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 49340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character: " + ch); 49426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 49726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 49840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen// Check if a given token is next. 49940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssenbool Parser::Is(int t) { 50040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return t == token_; 50126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 50226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 50326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 50440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Expect(int t) { 50526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 50640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("expecting: " + TokenToString(t) + " instead got: " + 50740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 50826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 50940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 51040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 51126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 51226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 51340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 51440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { 51540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 51639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += "."; 51739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += attribute_; 51839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen if (last) *last = attribute_; 51940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 52039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen } 52140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 52239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 52339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 52439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van OortmerssenEnumDef *Parser::LookupEnum(const std::string &id) { 52594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 52694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int components = static_cast<int>(namespaces_.back()->components.size()); 52794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components >= 0; components--) { 52840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto ed = enums_.Lookup( 52940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(id, components)); 53094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (ed) return ed; 53194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 53294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return nullptr; 53339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 53439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 53540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeIdent(Type &type) { 53639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen std::string id = attribute_; 53740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 53840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 53939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(id); 540d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def) { 541d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type = enum_def->underlying_type; 542d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 543d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 544d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 54539833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen type.struct_def = LookupCreateStruct(id); 546d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 54740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 548d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 549d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 55026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 55140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseType(Type &type) { 55226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) { 55326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.base_type = static_cast<BaseType>(token_ - kTokenNONE); 55440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 55526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 55626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == kTokenIdentifier) { 55740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(type)); 55826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == '[') { 55940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 56026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type subtype; 56140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(subtype)); 56226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 56326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this, but it will complicate things, and it's 56426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // easier to work around with a struct around the inner vector. 56540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 56640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested vector types not supported (wrap in table first)."); 56726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 5683fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 56926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.element = subtype.base_type; 57040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 57126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 57240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal type syntax"); 57326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 57626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 57726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 57840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 57940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const Type &type, FieldDef **dest) { 58026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 58126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 58226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 58326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 584df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez field.file = struct_def.file; 58526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 58626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 58726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 58826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 58926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 59026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 59126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 59226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 5931256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 59426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 59526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 59626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 59740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field already exists: " + name); 59840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &field; 59940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 60026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 60126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 60240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseField(StructDef &struct_def) { 60326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 604e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 605e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen if (name == struct_def.name) 606e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen return Error("field name can not be the same as table/struct name"); 607e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 608730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez std::vector<std::string> dc = doc_comment_; 60940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 61040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(':'); 61126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 61240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(type)); 61326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 61426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 61540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("structs_ may contain only scalar or struct fields"); 61626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6179140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 61826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 61926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 6209e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // with a special suffix. 6219e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 6229e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type.enum_def->underlying_type, &typefield)); 62368bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } else if (type.base_type == BASE_TYPE_VECTOR && 62468bbe983e9819bcbcd214cf84d73a440863ed6caBei Li type.element == BASE_TYPE_UNION) { 62568bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // Only cpp supports the union vector feature so far. 62668bbe983e9819bcbcd214cf84d73a440863ed6caBei Li if (opts.lang_to_generate != IDLOptions::kCpp) { 62768bbe983e9819bcbcd214cf84d73a440863ed6caBei Li return Error("Vectors of unions are not yet supported in all " 62868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li "the specified programming languages."); 62968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } 63068bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // For vector of union fields, add a second auto-generated vector field to 63168bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // hold the types, with a special suffix. 63268bbe983e9819bcbcd214cf84d73a440863ed6caBei Li Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def); 63368bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector.element = BASE_TYPE_UTYPE; 63468bbe983e9819bcbcd214cf84d73a440863ed6caBei Li ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 63568bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector, &typefield)); 63626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 63726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 63840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field; 63940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(AddField(struct_def, name, type, &field)); 64026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 64126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 64240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 64315dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 64440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("default values currently only supported for scalars"); 64540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(field->value)); 646fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen } 647fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (IsFloat(field->value.type.base_type)) { 648fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (!strpbrk(field->value.constant.c_str(), ".eE")) 649fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen field->value.constant += ".0"; 65026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 65126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6527b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen if (type.enum_def && 6537b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen IsScalar(type.base_type) && 6547b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !struct_def.fixed && 6557b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !type.enum_def->attributes.Lookup("bit_flags") && 656d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen !type.enum_def->ReverseLookup(static_cast<int>( 65740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StringToInt(field->value.constant.c_str())))) 65840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum " + type.enum_def->name + 6597b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen " does not have a declaration for this field\'s default of " + 66040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant); 6617b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen 66240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = dc; 663e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&field->attributes)); 66440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 66540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto hash_name = field->attributes.Lookup("hash"); 666d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (hash_name) { 667d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (type.base_type) { 668d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 669d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 670d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 67140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 32 bit types: " + 672d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 673d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 674d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 675d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 676d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 677d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 67840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 64 bit types: " + 679d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 680d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 681d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 682d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 68340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 68440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "only int, uint, long and ulong data types support hashing."); 685d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 686d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 687dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen auto cpp_type = field->attributes.Lookup("cpp_type"); 688dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (cpp_type) { 689dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (!hash_name) 690dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen return Error("cpp_type can only be used with a hashed field"); 691dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen } 69240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->deprecated && struct_def.fixed) 69340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("can't deprecate fields in a struct"); 69440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = field->attributes.Lookup("required") != nullptr; 69540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->required && (struct_def.fixed || 69640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(field->value.type.base_type))) 69740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only non-scalar fields in tables may be 'required'"); 69840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->key = field->attributes.Lookup("key") != nullptr; 69940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->key) { 7003550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen if (struct_def.has_key) 70140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only one field may be set as 'key'"); 7023550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen struct_def.has_key = true; 70340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(field->value.type.base_type)) { 70440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = true; 70540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_STRING) 70640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("'key' field must be string or scalar type"); 7073550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 7083550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 709641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 710641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen field->native_inline = field->attributes.Lookup("native_inline") != nullptr; 711641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen if (field->native_inline && !IsStruct(field->value.type)) 712641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen return Error("native_inline can only be defined on structs'"); 713641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 71440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto nested = field->attributes.Lookup("nested_flatbuffer"); 7153e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 7163e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 71740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 71840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute must be a string (the root type)"); 71940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 72040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 72140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 72240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute may only apply to a vector of ubyte"); 7233e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 7243e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 7253e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 7263e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 72726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 728dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->attributes.Lookup("flexbuffer")) { 7298f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen field->flexbuffer = true; 730dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen uses_flexbuffers_ = true; 731dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 732dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 733dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen return Error( 734dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen "flexbuffer attribute may only apply to a vector of ubyte"); 735dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen } 736dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen 7379140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 7389140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 7399140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 74040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto attr = field->attributes.Lookup("id"); 7419140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 7429140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 7439140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 7449140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 7459140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 7469140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 7479140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7489140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7499140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 75040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 75140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 75226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 75326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 754b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van OortmerssenCheckedError Parser::ParseString(Value &val) { 755b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen auto s = attribute_; 756b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen EXPECT(kTokenStringConstant); 757b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 758b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return NoError(); 759b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen} 760b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen 761f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van OortmerssenCheckedError Parser::ParseComma() { 762f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike) EXPECT(','); 763f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen return NoError(); 764f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen} 765f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen 76640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 7679e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen size_t parent_fieldn, 7689e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen const StructDef *parent_struct_def) { 76926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 77026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 77126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 7729e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen std::string constant; 773eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Find corresponding type field we may have already parsed. 774eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (auto elem = field_stack_.rbegin(); 775eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen elem != field_stack_.rbegin() + parent_fieldn; ++elem) { 776eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto &type = elem->second->value.type; 777eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UTYPE && 778eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen type.enum_def == val.type.enum_def) { 779eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen constant = elem->first.constant; 780eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen break; 781eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 782eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 783eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (constant.empty()) { 7849e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // We haven't seen the type field yet. Sadly a lot of JSON writers 7859e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // output these in alphabetical order, meaning it comes after this 7869e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // value. So we scan past the value to find it, then come back here. 7879e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_name = field->name + UnionTypeFieldSuffix(); 7889e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(parent_struct_def); 7899e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_field = parent_struct_def->fields.Lookup(type_name); 7909e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(type_field); // Guaranteed by ParseField(). 7919e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Remember where we are in the source file, so we can come back here. 7929e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto backup = *static_cast<ParserState *>(this); 7939e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(SkipAnyJsonValue()); // The table. 794f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 7959e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto next_name = attribute_; 7969e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (Is(kTokenStringConstant)) { 7979e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen NEXT(); 7989e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7999e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(kTokenIdentifier); 8009e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 8019e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (next_name != type_name) 8029e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen return Error("missing type field after this union value: " + 8039e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type_name); 8049e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(':'); 8059e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen Value type_val = type_field->value; 8069e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 8079e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = type_val.constant; 8089e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Got the information we needed, now rewind: 8099e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen *static_cast<ParserState *>(this) = backup; 8109e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 81140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uint8_t enum_idx; 8129e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(atot(constant.c_str(), *this, &enum_idx)); 8133fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 81440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("illegal type id for: " + field->name); 815b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) { 816b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant, 817b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen nullptr)); 818b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.struct_def->fixed) { 819b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen // All BASE_TYPE_UNION values are offsets, so turn this into one. 820b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen SerializeStruct(*enum_val->union_type.struct_def, val); 821b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen builder_.ClearOffsets(); 822b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.GetSize()); 823b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 824b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) { 825b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 826b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 827b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen assert(false); 828b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 82926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 83026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 83126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 83240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 83326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 83426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 835b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 83626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 83726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 83826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 83940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t off; 84040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseVector(val.type.VectorType(), &off)); 84140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val.constant = NumToString(off); 84226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 84326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 844d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 845d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: 846d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 847d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 848d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (field && field->attributes.Lookup("hash") && 849d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 85040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHash(val, field)); 851d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } else { 85240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 853d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 854d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 855d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 85626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 85740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 85826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 85926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 86040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 86126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 86226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 86326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 8644d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(val.constant.length() == struct_def.bytesize); 86526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 8664d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 8674d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 86826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 86926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 87026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8718f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTableDelimiters(size_t &fieldn, 8728f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen const StructDef *struct_def, 8738f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen const std::function<CheckedError(const std::string &name)> &body) { 8748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen // We allow tables both as JSON object{ .. } with field names 875b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud // or vector[..] with all fields in order 8768f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen char terminator = '}'; 8778f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen bool is_nested_vector = struct_def && Is('['); 8788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 879b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 8808f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen terminator = ']'; 881b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 882b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT('{'); 883b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8846c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 8858f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !fieldn) && Is(terminator)) break; 886b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud std::string name; 8878f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 8888f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (fieldn > struct_def->fields.vec.size()) { 889b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud return Error("too many unnamed fields in nested array"); 890b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8918f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen name = struct_def->fields.vec[fieldn]->name; 89240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 893b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud name = attribute_; 894b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud if (Is(kTokenStringConstant)) { 895b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 896b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 897b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 898b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 899f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':'); 90040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 9018f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(body(name)); 9028f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(terminator)) break; 903f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 9048f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 9058f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 9068f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector && fieldn != struct_def->fields.vec.size()) { 9078f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("wrong number of unnamed fields in table vector"); 9088f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 9098f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 9108f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 9118f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 9128f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 9138f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen uoffset_t *ovalue) { 9148f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t fieldn = 0; 9158f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto err = ParseTableDelimiters(fieldn, &struct_def, 9168f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen [&](const std::string &name) -> CheckedError { 9172e2063cbeb6ea95c804796c443153f71797c3629schoetbi if (name == "$schema") { 9182e2063cbeb6ea95c804796c443153f71797c3629schoetbi EXPECT(kTokenStringConstant); 9192e2063cbeb6ea95c804796c443153f71797c3629schoetbi return NoError(); 9202e2063cbeb6ea95c804796c443153f71797c3629schoetbi } 9218f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto field = struct_def.fields.Lookup(name); 92213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!field) { 92313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!opts.skip_unexpected_fields_in_json) { 92413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return Error("unknown field: " + name); 92513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 92613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 92713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 92813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 929049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (Is(kTokenNull)) { 930049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen NEXT(); // Ignore this field. 931049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } else { 932049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen Value val = field->value; 9338f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (field->flexbuffer) { 9348f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder builder(1024, 9358f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::BUILDER_FLAG_SHARE_ALL); 9368f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(ParseFlexBufferValue(&builder)); 9378f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder.Finish(); 9388f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto off = builder_.CreateVector(builder.GetBuffer()); 9398f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen val.constant = NumToString(off.o); 9408f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } else { 9418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(ParseAnyValue(val, field, fieldn, &struct_def)); 9428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 943049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // Hardcoded insertion-sort with error-check. 944049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // If fields are specified in order, then this loop exits immediately. 945eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto elem = field_stack_.rbegin(); 946eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (; elem != field_stack_.rbegin() + fieldn; ++elem) { 947eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto existing_field = elem->second; 948049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field == field) 949049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return Error("field set more than once: " + field->name); 950049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field->value.offset < field->value.offset) break; 951049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 952eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Note: elem points to before the insertion point, thus .base() points 953eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // to the correct spot. 954eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen field_stack_.insert(elem.base(), std::make_pair(val, field)); 955049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen fieldn++; 95613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 9574d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen } 9588f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 9598f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen }); 9608f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 96155dec4d2f8817ede5a98d302d0b947c759f97098sfariv 96255dec4d2f8817ede5a98d302d0b947c759f97098sfariv // Check if all required fields are parsed. 96355dec4d2f8817ede5a98d302d0b947c759f97098sfariv for (auto field_it = struct_def.fields.vec.begin(); 96455dec4d2f8817ede5a98d302d0b947c759f97098sfariv field_it != struct_def.fields.vec.end(); 96555dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++field_it) { 96655dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto required_field = *field_it; 96755dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!required_field->required) { 96855dec4d2f8817ede5a98d302d0b947c759f97098sfariv continue; 96955dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 97055dec4d2f8817ede5a98d302d0b947c759f97098sfariv bool found = false; 97155dec4d2f8817ede5a98d302d0b947c759f97098sfariv for (auto pf_it = field_stack_.end() - fieldn; 97255dec4d2f8817ede5a98d302d0b947c759f97098sfariv pf_it != field_stack_.end(); 97355dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++pf_it) { 97455dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto parsed_field = pf_it->second; 97555dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (parsed_field == required_field) { 97655dec4d2f8817ede5a98d302d0b947c759f97098sfariv found = true; 97755dec4d2f8817ede5a98d302d0b947c759f97098sfariv break; 97855dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 97955dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 98055dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!found) { 98155dec4d2f8817ede5a98d302d0b947c759f97098sfariv return Error("required field is missing: " + required_field->name + " in " + struct_def.name); 98255dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 98326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 98413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 98526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && fieldn != struct_def.fields.vec.size()) 98640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("struct: wrong number of initializers: " + struct_def.name); 9874d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen 98826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 98926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 99026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 99126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 99226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 99326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 99426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 99526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 99626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = field_stack_.rbegin(); 99726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 998721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma auto &field_value = it->first; 99926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 100040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.sortbysize || 100140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen size == SizeOf(field_value.type.base_type)) { 1002721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma switch (field_value.type.base_type) { 100348dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 100448dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 100526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 100626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 1007be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 100840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 100940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 101040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(val); \ 1011be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 101240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val, valdef; \ 101340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 101440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 101540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddElement(field_value.offset, val, valdef); \ 1016be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 101726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 101826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 101926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 102048dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 102148dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 102226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 102326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 102426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 1025721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma SerializeStruct(*field->value.type.struct_def, field_value); \ 102626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 102740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 102840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 102940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddOffset(field_value.offset, val); \ 103026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 103126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 103226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 103326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 103426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 103826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t i = 0; i < fieldn; i++) field_stack_.pop_back(); 103926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 104026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 104126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 104226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 10434d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(value); 10444d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // Temporarily store this struct in the value string, since it is to 10454d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // be serialized in-place elsewhere. 10464d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen value->assign( 10474d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 10484d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 104926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 105040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen assert(!ovalue); 105126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 105240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto val = builder_.EndTable(start, 105340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen static_cast<voffset_t>(struct_def.fields.vec.size())); 105440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (ovalue) *ovalue = val; 105540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (value) *value = NumToString(val); 105626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 105740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 105826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 105926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10608f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVectorDelimiters(size_t &count, 10618f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen const std::function<CheckedError()> &body) { 10628f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT('['); 10636c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 10648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !count) && Is(']')) break; 10658f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(body()); 10668f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen count++; 10678f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(']')) break; 1068f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 10698f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 10708f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 10718f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 10728f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 10738f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 10748f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 10758f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 107635cbd23f63003f86b72889d47a7f5afb1fc6de51Wouter van Oortmerssen auto err = ParseVectorDelimiters(count, [&]() -> CheckedError { 107726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 107826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.type = type; 10799e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(val, nullptr, 0, nullptr)); 108026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.push_back(std::make_pair(val, nullptr)); 10818f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 10828f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen }); 10838f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 108426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1085be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 1086be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 10878f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen for (size_t i = 0; i < count; i++) { 108826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 108926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 109026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 109148dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 109226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 109326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 109440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen else { \ 109540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE elem; \ 109640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 109740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(elem); \ 109840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } \ 109926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 110026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 110126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 110226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 110326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 110426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 110526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 110626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 110740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *ovalue = builder_.EndVector(count); 110840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 110926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 111026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1111e6b79f00022aee3108427977c9823ff57154e1c6Wouter van OortmerssenCheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 111240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('(')) { 111340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 111426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 111526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 111640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 11170952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen if (known_attributes_.find(name) == known_attributes_.end()) 111840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("user define attributes must be declared before use: " + 111940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen name); 112026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 1121e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen attributes->Add(name, e); 112240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(':')) { 112340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 112440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(*e)); 112526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 112640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(')')) { NEXT(); break; } 112740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 112826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 112926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 113040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 113126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 113226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 113340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e, 113440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BaseType req, bool *destmatch) { 113526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 113626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 113740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *destmatch = true; 113826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 113926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 114026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 114126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 114226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 114340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error(std::string("type mismatch: expecting: ") + 114440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[e.type.base_type] + 114540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ", found: " + 114640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[req]); 114726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 114826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 114940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 115026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 115226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 115326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1154fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van OortmerssenCheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 115540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result = 0; 11569c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 11579c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 11589c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 11599c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 11609c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 11619c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 11629c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 11639c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 11649c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 11659c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 11669c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 11679c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 11689c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 11699c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 11709c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 117140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown enum value: " + word + 11729c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 117340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 11749c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 11759c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 117640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("not a valid value for this field: " + word); 11779c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 117839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen const char *dot = strrchr(word.c_str(), '.'); 117940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!dot) 118040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values need to be qualified by an enum type"); 11819c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 11829c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 118339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(enum_def_str); 118440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_def) return Error("unknown enum: " + enum_def_str); 11859c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 118640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("unknown enum value: " + enum_val_str); 118740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 11889c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 11899c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 119040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11919c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 11929c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 1193d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 119440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHash(Value &e, FieldDef* field) { 1195d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(field); 1196d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames Value *hash_name = field->attributes.Lookup("hash"); 1197d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (e.type.base_type) { 119846497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_INT: { 119946497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction32(hash_name->constant.c_str()); 120046497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str())); 120146497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 120246497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 120346497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1204d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 1205d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction32(hash_name->constant.c_str()); 1206d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint32_t hashed_value = hash(attribute_.c_str()); 1207d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1208d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1209d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 121046497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_LONG: { 121146497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction64(hash_name->constant.c_str()); 121246497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str())); 121346497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 121446497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 121546497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1216d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 1217d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction64(hash_name->constant.c_str()); 1218d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint64_t hashed_value = hash(attribute_.c_str()); 1219d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1220d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1221d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1222d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 1223d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(0); 1224d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 122540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 122640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1227d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames} 1228d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 12298f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::TokenError() { 12308f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("cannot parse value starting with: " + 12318f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen TokenToStringId(token_)); 12328f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 12338f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 123440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseSingleValue(Value &e) { 1235d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // First see if this could be a conversion function: 1236d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (token_ == kTokenIdentifier && *cursor_ == '(') { 1237d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto functionname = attribute_; 1238d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen NEXT(); 1239d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT('('); 1240d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen ECHECK(ParseSingleValue(e)); 1241d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT(')'); 1242d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1243d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (functionname == name) { \ 1244d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto x = strtod(e.constant.c_str(), nullptr); \ 1245d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen e.constant = NumToString(op); \ 1246d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } 1247d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("deg", x / M_PI * 180); 1248d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("rad", x * M_PI / 180); 1249d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1250d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1251d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1252d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1253d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1254d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1255d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // TODO(wvo): add more useful conversion functions here. 1256d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #undef FLATBUFFERS_FN_DOUBLE 1257d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // Then check if this could be a string/identifier enum value: 1258d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } else if (e.type.base_type != BASE_TYPE_STRING && 12599c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 12609c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 1261fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(attribute_[0])) { // Enum value. 1262fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen int64_t val; 1263fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen ECHECK(ParseEnumFromString(e.type, &val)); 1264fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(val); 1265fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen NEXT(); 1266fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { // Numeric constant in string. 1267fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsInteger(e.type.base_type)) { 1268b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1269b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(StringToInt(attribute_.c_str(), &end)); 1270b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1271b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid integer: " + attribute_); 1272fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else if (IsFloat(e.type.base_type)) { 1273b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1274b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(strtod(attribute_.c_str(), &end)); 1275b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1276b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid float: " + attribute_); 1277fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { 1278fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen assert(0); // Shouldn't happen, we covered all types. 1279fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = "0"; 1280fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 128183dc5ed4a7267c78fb3f00e972de4db30762166dWouter van Oortmerssen NEXT(); 1282fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 128326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 128440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool match = false; 128540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenIntegerConstant, 128640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(e.type.base_type), 128740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 128840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_INT, 128940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 129040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenFloatConstant, 129140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsFloat(e.type.base_type), 129240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 129340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_FLOAT, 129440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 129540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenStringConstant, 129640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 129740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 129840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_STRING, 129940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 13008f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (!match) return TokenError(); 130126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 130240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 130326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 130426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 130594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name, 130694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool create_if_new, bool definition) { 130794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string qualified_name = namespaces_.back()->GetFullyQualifiedName(name); 130820c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an unqualified use. 130994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto struct_def = structs_.Lookup(name); 131094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 131194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 131220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace, and is registered under its 131320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // qualified name. 131494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 131594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Move(name, qualified_name); 131694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 131794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return struct_def; 131894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 131920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an qualified use. 132094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup(qualified_name); 132120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 132220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (definition) { 132320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace. 132420c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 132520c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 132620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen return struct_def; 132720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 132894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!definition) { 132994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 133094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t components = namespaces_.back()->components.size(); 133194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components && !struct_def; components--) { 133294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup( 133394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name, components - 1)); 133494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 133594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 133694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!struct_def && create_if_new) { 133726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 133894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 133994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(qualified_name, struct_def); 134094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 134194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 134294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 134394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Not a definition. 134494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 134594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 134694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // It is defined in the root namespace, since we don't know what the 134794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // final namespace will be. 134894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: maybe safer to use special namespace? 134994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(name, struct_def); 135094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 135194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = new Namespace(); 135294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), struct_def->defined_namespace); 135394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 135426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 135526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 135626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 135726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 135840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1359c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::vector<std::string> enum_comment = doc_comment_; 136040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1361c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::string enum_name = attribute_; 136240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 136326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 1364c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.name = enum_name; 136540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen enum_def.file = file_being_parsed_; 1366c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.doc_comment = enum_comment; 136726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 13687b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen enum_def.defined_namespace = namespaces_.back(); 136994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enums_.Add(namespaces_.back()->GetFullyQualifiedName(enum_name), 137094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen &enum_def)) 137140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum already exists: " + enum_name); 137226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 137326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 137426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 1375a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 137645bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode) { 137794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_INT; 1378d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 1379d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Give specialized error message, since this type spec used to 1380d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // be optional in the first FlatBuffers release. 138140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(':')) { 138240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("must specify the underlying integer type for this" 138340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 138440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 138540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 138640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 1387d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Specify the integer type underlying this enum. 138840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(enum_def.underlying_type)); 1389d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 139040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("underlying enum type must be integral"); 1391d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 13923fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 13933fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 139426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1395e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&enum_def.attributes)); 139640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 139726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 139840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 139945bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode && attribute_ == "option") { 140040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 140194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 140294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value_name = attribute_; 140394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto full_name = value_name; 140494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> value_comment = doc_comment_; 140540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14063639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen if (is_union) { 14073639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen ECHECK(ParseNamespacing(&full_name, &value_name)); 1408d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen if (opts.union_value_namespacing) { 1409d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // Since we can't namespace the actual enum identifiers, turn 1410d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // namespace parts into part of the identifier. 1411d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen value_name = full_name; 1412d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen std::replace(value_name.begin(), value_name.end(), '.', '_'); 1413d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen } 14143639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen } 141594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 141694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value = enum_def.vals.vec.size() 141794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 141894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen : 0; 141994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &ev = *new EnumVal(value_name, value); 142094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enum_def.vals.Add(value_name, &ev)) 142140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum value already exists: " + value_name); 142294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.doc_comment = value_comment; 142394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (is_union) { 1424b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (Is(':')) { 1425b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen NEXT(); 1426b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseType(ev.union_type)); 1427b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (ev.union_type.base_type != BASE_TYPE_STRUCT && 1428b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type.base_type != BASE_TYPE_STRING) 1429b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return Error("union value type may only be table/struct/string"); 1430b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen enum_def.uses_type_aliases = true; 1431b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 1432b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name)); 1433b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 143494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 143540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('=')) { 143640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1437d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen ev.value = StringToInt(attribute_.c_str()); 143840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 143945bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (!opts.proto_mode && prevsize && 144094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.vals.vec[prevsize - 1]->value >= ev.value) 144140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values must be specified in ascending order"); 144294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 14439d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (is_union) { 14449d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (ev.value < 0 || ev.value >= 256) 14459d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen return Error("union enum value must fit in a ubyte"); 14469d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen } 144740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && Is('[')) { 144840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 144994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // ignore attributes on enums. 145040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != ']') NEXT(); 145140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 145294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 145326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 145440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(opts.proto_mode ? ';' : ',')) break; 145540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 145640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) break; 145740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 145840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1459127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 1460127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1461127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 1462127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 1463127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 146440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("bit flag out of range of underlying integral type"); 14659c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 1466127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 1467127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 146840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (dest) *dest = &enum_def; 14699b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen types_.Add(namespaces_.back()->GetFullyQualifiedName(enum_def.name), 14709b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_UNION, nullptr, &enum_def)); 147140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 147226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 147326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 147440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 147594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name, true, true); 147640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.predecl) return Error("datatype already exists: " + name); 147726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 147826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 147940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def.file = file_being_parsed_; 148026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 1481d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // to preserve declaration order. 1482370693a200cf2a6eb58be5d17fe6482f3e05c067Dmitry Ermolov *std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; 148340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &struct_def; 148440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1485d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1486d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1487b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra PenkeCheckedError Parser::CheckClash(std::vector<FieldDef*> &fields, 1488b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke StructDef *struct_def, 1489b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke const char *suffix, 1490b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke BaseType basetype) { 1491b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto len = strlen(suffix); 1492b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke for (auto it = fields.begin(); it != fields.end(); ++it) { 1493b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto &fname = (*it)->name; 1494b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (fname.length() > len && 1495b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.compare(fname.length() - len, len, suffix) == 0 && 1496b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1497b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto field = struct_def->fields.Lookup( 1498b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.substr(0, fname.length() - len)); 1499b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (field && field->value.type.base_type == basetype) 1500b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return Error("Field " + fname + 1501b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke " would clash with generated functions for field " + 1502b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke field->name); 1503b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1504b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1505b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return NoError(); 1506b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1507d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen 1508b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1509b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1510b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1511b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a_id < b_id; 1512b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1513b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 151440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseDecl() { 1515d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen std::vector<std::string> dc = doc_comment_; 151640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool fixed = Is(kTokenStruct); 151740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (fixed) NEXT() else EXPECT(kTokenTable); 151894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 151940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 152040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StructDef *struct_def; 152140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 152240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->doc_comment = dc; 152340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->fixed = fixed; 1524e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&struct_def->attributes)); 152540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->sortbysize = 152640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 152740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 152840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != '}') ECHECK(ParseField(*struct_def)); 152940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto force_align = struct_def->attributes.Lookup("force_align"); 153026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 153126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 153226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 153340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen align < struct_def->minalign || 15346862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen align > FLATBUFFERS_MAX_ALIGNMENT || 153526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 153640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("force_align must be a power of two integer ranging from the" 15376862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen "struct\'s natural alignment to " + 15386862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen NumToString(FLATBUFFERS_MAX_ALIGNMENT)); 153940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->minalign = align; 154026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 154140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->PadLastField(struct_def->minalign); 15429140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 154340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &fields = struct_def->fields.vec; 154440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def->fixed && fields.size()) { 15457fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 15469140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 15479140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 15489140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 15499140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 15509140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 15519140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 15529140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 155340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 155440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "either all fields or no fields must have an 'id' attribute"); 15559140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 15569140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 1557b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(fields.begin(), fields.end(), compareFieldDefs); 15589140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 15599140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 15609140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 156140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field id\'s must be consecutive from 0, id " + 15629140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 15639140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 15649140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 15659140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 15669140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 1567b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 15689e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), 15699e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen BASE_TYPE_UNION)); 1570b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1571b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1572b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1573b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1574b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 157540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 15769b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen types_.Add(namespaces_.back()->GetFullyQualifiedName(struct_def->name), 15779b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_STRUCT, struct_def, nullptr)); 157840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 157926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 158026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15811a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van OortmerssenCheckedError Parser::ParseService() { 15821a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen std::vector<std::string> service_comment = doc_comment_; 15831a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 15841a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto service_name = attribute_; 15851a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 15861a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &service_def = *new ServiceDef(); 15871a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.name = service_name; 15881a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.file = file_being_parsed_; 15891a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.doc_comment = service_comment; 15901a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.defined_namespace = namespaces_.back(); 15911a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (services_.Add(namespaces_.back()->GetFullyQualifiedName(service_name), 15921a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen &service_def)) 15931a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("service already exists: " + service_name); 1594e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&service_def.attributes)); 15951a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('{'); 15961a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen do { 15971a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto rpc_name = attribute_; 15981a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 15991a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('('); 16001a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen Type reqtype, resptype; 16011a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(reqtype)); 16021a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(')'); 16031a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(':'); 16041a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(resptype)); 16051a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 16061a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 16071a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc request and response types must be tables"); 16081a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &rpc = *new RPCCall(); 16091a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.name = rpc_name; 16101a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.request = reqtype.struct_def; 16111a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.response = resptype.struct_def; 16121a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (service_def.calls.Add(rpc_name, &rpc)) 16131a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc already exists: " + rpc_name); 1614e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&rpc.attributes)); 16151a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(';'); 16161a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } while (token_ != '}'); 16171a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 16181a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 16191a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen} 16201a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen 162126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 16224dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup(name); 16234dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen if (!root_struct_def_) 16244dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup( 16254dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name)); 162681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return root_struct_def_ != nullptr; 162726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 162826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1629be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 16303881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // This function marks all existing definitions as having already 16313881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // been generated, which signals no code for included files should be 16323881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // generated. 1633be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 1634be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 1635be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1636be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 1637be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 1638be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 16390e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (!(*it)->predecl) { 16400e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath (*it)->generated = true; 16410e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 1642be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 164348f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen for (auto it = services_.vec.begin(); 164448f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen it != services_.vec.end(); ++it) { 164548f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen (*it)->generated = true; 164648f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen } 1647be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 1648be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 164940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespace() { 165040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1651d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen auto ns = new Namespace(); 1652d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen namespaces_.push_back(ns); 165394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ != ';') { 165494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (;;) { 165594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(attribute_); 165640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 165740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT() else break; 165894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1659d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 166040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 166140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1662d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1663d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1664b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareEnumVals(const EnumVal *a, const EnumVal* b) { 1665b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a->value < b->value; 1666b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1667b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 1668d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Best effort parsing of .proto declarations, with the aim to turn them 1669d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// in the closest corresponding FlatBuffer equivalent. 1670d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// We parse everything as identifiers instead of keywords, since we don't 1671d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// want protobuf keywords to become invalid identifiers in FlatBuffers. 167240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoDecl() { 167394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool isextend = attribute_ == "extend"; 1674d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == "package") { 1675d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // These are identical in syntax to FlatBuffer's namespace decl. 167640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 167794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "message" || isextend) { 16783ad853630c6bf76a9c8fc2a15e3fc40cd52de691Advay Mengle std::vector<std::string> struct_comment = doc_comment_; 167940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 168094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *struct_def = nullptr; 168194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 168240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 168394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto id = attribute_; 168440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 168540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 168694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = LookupCreateStruct(id, false); 168740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def) 168840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot extend unknown message type: " + id); 168994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 169094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 169140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 169240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 169394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Since message definitions can be nested, we create a new namespace. 169494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = new Namespace(); 169594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Copy of current namespace. 169694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen *ns = *namespaces_.back(); 169794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // But with current message name. 169894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(name); 169994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(ns); 170094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 170194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->doc_comment = struct_comment; 170240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(struct_def, isextend, false)); 170394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!isextend) { 170494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We have to remove the nested namespace, but we can't just throw it 170594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // away, so put it at the beginning of the vector. 170694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = namespaces_.back(); 170794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.pop_back(); 170894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), ns); 170994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 171040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 171194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "enum") { 171294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // These are almost the same, just with different terminator: 171340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EnumDef *enum_def; 171440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, &enum_def)); 171540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 171694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protobuf allows them to be specified in any order, so sort afterwards. 171740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &v = enum_def->vals.vec; 1718d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen std::sort(v.begin(), v.end(), compareEnumVals); 1719b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 172094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: remove any duplicates, as .fbs files can't handle them. 172194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (auto it = v.begin(); it != v.end(); ) { 172294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it); 172394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else ++it; 172494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 172594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "syntax") { // Skip these. 172640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 172740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 172840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 172940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 173094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 173140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 173240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 173394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "service") { // Skip these. 173440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 173540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 173640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 173794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 173840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("don\'t know how to parse .proto declaration starting with " + 173994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen TokenToStringId(token_)); 174094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 174140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 174294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 174394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 174440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 174540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool inside_oneof) { 174640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 174794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (token_ != '}') { 174894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "message" || attribute_ == "extend" || 174994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_ == "enum") { 175094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Nested declarations. 175140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 175294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "extensions") { // Skip these. 175340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 175440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 175540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenIdentifier)) { 175640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // to 175740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // num 175894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 175940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 176094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 176140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 176240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 176394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "reserved") { // Skip these. 176440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 176540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 176640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } 176740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 176894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 176994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> field_comment = doc_comment_; 177094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Parse the qualifier. 177194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool required = false; 177294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool repeated = false; 177394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool oneof = false; 177494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!inside_oneof) { 17752abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen if (attribute_ == "optional") { 17762abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // This is the default. 177740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 17782abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "required") { 17792abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen required = true; 178040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 17812abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "repeated") { 17822abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen repeated = true; 178340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 178494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "oneof") { 178594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen oneof = true; 178640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 17872abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else { 178894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // can't error, proto3 allows decls without any of the above. 17892abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } 179094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 179194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *anonymous_struct = nullptr; 179294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen Type type; 179394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "group" || oneof) { 179440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!oneof) EXPECT(kTokenIdentifier); 179594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto name = "Anonymous" + NumToString(anonymous_counter++); 179640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &anonymous_struct)); 179794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type = Type(BASE_TYPE_STRUCT, anonymous_struct); 179894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 179940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeFromProtoType(&type)); 180094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 180194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Repeated elements get mapped to a vector. 180294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (repeated) { 180394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.element = type.base_type; 180494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.base_type = BASE_TYPE_VECTOR; 180594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 180694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 180794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protos may use our keywords "attribute" & "namespace" as an identifier. 180840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenAttribute) || Is(kTokenNameSpace)) { 180940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 181094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: simpler to just not make these keywords? 181194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen name += "_"; // Have to make it not a keyword. 181294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 181340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 181494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 181594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!oneof) { 18162abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // Parse the field id. Since we're just translating schemas, not 18172abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // any kind of binary compatibility, we can safely ignore these, and 18182abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // assign our own. 181940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 182040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 182194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 182240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field = nullptr; 182394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 182494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We allow a field to be re-defined when extending. 182594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: are there situations where that is problematic? 182640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field = struct_def->fields.Lookup(name); 182794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 182840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 182940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = field_comment; 183040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(type.base_type)) field->required = required; 183194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // See if there's a default specified. 183240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('[')) { 183340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 183440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 183594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto key = attribute_; 183640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 183740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 183894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto val = attribute_; 183940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 184094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (key == "default") { 184194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: skip non-numeric defaults (enums). 184294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto numeric = strpbrk(val.c_str(), "0123456789-+."); 184394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (IsScalar(type.base_type) && numeric == val.c_str()) 184440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant = val; 184594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (key == "deprecated") { 184640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = val == "true"; 184794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 184840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(',')) break; 184940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 185040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 185140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 185294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 185394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (anonymous_struct) { 185440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 185540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 185694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 185740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 1858d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1859d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 186094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 186140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 186240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 186394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 186494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 186540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoKey() { 186694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '(') { 186740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 186894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Skip "(a.b)" style custom attributes. 186940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 187040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(')'); 187140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { NEXT(); EXPECT(kTokenIdentifier); } 187294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 187340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 187494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 187540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 187694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 187794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 187840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoCurliesOrIdent() { 187940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('{')) { 188040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 188194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int nesting = 1; nesting; ) { 188294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '{') nesting++; 188394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else if (token_ == '}') nesting--; 188440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 188594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1886d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 188740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // Any single token. 1888d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 188940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1890d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1891d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 189240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoOption() { 189340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 189440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 189540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 189640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 189740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 189894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 189994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 1900d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Parse a protobuf type, and map it to the corresponding FlatBuffer one. 190140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeFromProtoType(Type *type) { 1902d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen struct type_lookup { const char *proto_type; BaseType fb_type; }; 1903d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen static type_lookup lookup[] = { 1904d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "float", BASE_TYPE_FLOAT }, { "double", BASE_TYPE_DOUBLE }, 1905d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "int32", BASE_TYPE_INT }, { "int64", BASE_TYPE_LONG }, 1906d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "uint32", BASE_TYPE_UINT }, { "uint64", BASE_TYPE_ULONG }, 1907d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sint32", BASE_TYPE_INT }, { "sint64", BASE_TYPE_LONG }, 1908d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "fixed32", BASE_TYPE_UINT }, { "fixed64", BASE_TYPE_ULONG }, 1909d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sfixed32", BASE_TYPE_INT }, { "sfixed64", BASE_TYPE_LONG }, 1910d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bool", BASE_TYPE_BOOL }, 1911d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "string", BASE_TYPE_STRING }, 1912d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bytes", BASE_TYPE_STRING }, 1913d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { nullptr, BASE_TYPE_NONE } 1914d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen }; 1915d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen for (auto tl = lookup; tl->proto_type; tl++) { 1916d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == tl->proto_type) { 191740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen type->base_type = tl->fb_type; 191840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 191940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1920d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1921d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 192240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 192340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(*type)); 192440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1925d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1926d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 192713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipAnyJsonValue() { 192813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke switch (token_) { 19298f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 19308f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t fieldn = 0; 19318f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ParseTableDelimiters(fieldn, nullptr, 19328f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen [&](const std::string &) -> CheckedError { 19338f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(SkipAnyJsonValue()); 19348f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen fieldn++; 19358f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 19368f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen }); 19378f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 19388f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[': { 19398f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 19408f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ParseVectorDelimiters(count, [&]() { return SkipAnyJsonValue(); }); 19418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 194213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenStringConstant: 19438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenStringConstant); 194413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 194513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenIntegerConstant: 194613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenIntegerConstant); 194713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 194813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenFloatConstant: 194913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenFloatConstant); 195013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 195113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke default: 19528f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return TokenError(); 195313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 195413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 195513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 195613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 19578f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { 19588f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen switch (token_) { 19598f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 19608f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartMap(); 19618f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t fieldn = 0; 19628f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto err = ParseTableDelimiters(fieldn, nullptr, 19638f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen [&](const std::string &name) -> CheckedError { 19648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Key(name); 19658f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(ParseFlexBufferValue(builder)); 19668f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen fieldn++; 19678f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 19688f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen }); 19698f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 19708f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndMap(start); 19718f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 1972cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 19738f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[':{ 19748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartVector(); 19758f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 19768f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(ParseVectorDelimiters(count, [&]() { 19778f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ParseFlexBufferValue(builder); 19788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen })); 19798f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndVector(start, false, false); 19808f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 1981cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 19828f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenStringConstant: 19838f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->String(attribute_); 19848f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenStringConstant); 19858f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 19868f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenIntegerConstant: 19878f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Int(StringToInt(attribute_.c_str())); 19888f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 19898f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 19908f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenFloatConstant: 19918f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Double(strtod(attribute_.c_str(), nullptr)); 19928f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenFloatConstant); 19938f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 19948f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen default: 19958f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return TokenError(); 199613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 199713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 199813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 199913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 20008f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssenbool Parser::ParseFlexBuffer(const char *source, const char *source_filename, 20018f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder *builder) { 20028f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto ok = !StartParseFile(source, source_filename).Check() && 20038f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen !ParseFlexBufferValue(builder).Check(); 20048f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (ok) builder->Finish(); 20058f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ok; 200613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 200713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 200830642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths, 200930642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen const char *source_filename) { 20100e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return !ParseRoot(source, include_paths, source_filename).Check(); 201140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen} 201240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 20138f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::StartParseFile(const char *source, const char *source_filename) { 20148f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen file_being_parsed_ = source_filename ? source_filename : ""; 20158f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen source_ = cursor_ = source; 20168f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen line_ = 1; 20178f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen error_.clear(); 20188f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(SkipByteOrderMark()); 20198f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 20208f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(kTokenEof)) 20218f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("input file is empty"); 20228f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 20238f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 20248f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 20250e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::ParseRoot(const char *source, const char **include_paths, 20260e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename) { 20270e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ECHECK(DoParse(source, include_paths, source_filename, nullptr)); 20280e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 20290e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // Check that all types were defined. 20300e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 20310e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if ((*it)->predecl) { 20320e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return Error("type referenced but not defined: " + (*it)->name); 20330e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20340e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20350e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 20360e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // This check has to happen here and not earlier, because only now do we 20370e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // know for sure what the type of these are. 20380e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 20390e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &enum_def = **it; 20400e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (enum_def.is_union) { 20410e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto val_it = enum_def.vals.vec.begin(); 20420e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val_it != enum_def.vals.vec.end(); 20430e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ++val_it) { 20440e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &val = **val_it; 20450e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (opts.lang_to_generate != IDLOptions::kCpp && 20460e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val.union_type.struct_def && val.union_type.struct_def->fixed) 20470e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return Error( 20480e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath "only tables can be union elements in the generated language: " 20490e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath + val.name); 20500e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20510e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20520e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20530e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return NoError(); 20540e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath} 20550e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 20560e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::DoParse(const char *source, 20570e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char **include_paths, 20580e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename, 20590e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *include_filename) { 2060df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (source_filename && 2061642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_.find(source_filename) == included_files_.end()) { 2062642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_[source_filename] = include_filename ? include_filename : ""; 2063df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez files_included_per_file_[source_filename] = std::set<std::string>(); 2064df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2065df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (!include_paths) { 20661e6f8f5b8c4d0407d7db750858e7863e07091958Wouter van Oortmerssen static const char *current_directory[] = { "", nullptr }; 2067df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez include_paths = current_directory; 2068df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2069fea6b525ee57bf61d307abc16ade8d9041a3a01dYonggang Li field_stack_.clear(); 207026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 207194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Start with a blank namespace just in case this file doesn't have one. 207294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(new Namespace()); 2073e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 20748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(StartParseFile(source, source_filename)); 2075e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 207640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Includes must come before type declarations: 207740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 207840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Parse pre-include proto statements if any: 207940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && 208040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (attribute_ == "option" || attribute_ == "syntax" || 208140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "package")) { 208240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 20833f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen } else if (Is(kTokenNativeInclude)) { 20843f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen NEXT(); 20853f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen native_included_files_.emplace_back(attribute_); 20863f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen EXPECT(kTokenStringConstant); 208740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (Is(kTokenInclude) || 208840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (opts.proto_mode && 208940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "import" && 209040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Is(kTokenIdentifier))) { 209140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 209240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && attribute_ == "public") NEXT(); 2093aaf5598a032314767721fead8a0acf9ca37c5e09Wouter van Oortmerssen auto name = flatbuffers::PosixPath(attribute_.c_str()); 209440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 209540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Look for the file in include_paths. 209640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string filepath; 209740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 209840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen filepath = flatbuffers::ConCatPathFileName(*paths, name); 209940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if(FileExists(filepath.c_str())) break; 2100be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 210140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (filepath.empty()) 210240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to locate include file: " + name); 210340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (source_filename) 210440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen files_included_per_file_[source_filename].insert(filepath); 2105642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov if (included_files_.find(filepath) == included_files_.end()) { 210640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We found an include file that we have not parsed yet. 210740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Load it and parse it. 210840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string contents; 210940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!LoadFile(filepath.c_str(), true, &contents)) 211040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to load include file: " + name); 211122743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(), 211222743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen name.c_str())); 211340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We generally do not want to output code for any included files: 211440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!opts.generate_all) MarkGenerated(); 211540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is the easiest way to continue this file after an include: 211640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 211740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // file anew. This will cause it to encounter the same include 211840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statement again, but this time it will skip it, because it was 211940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // entered into included_files_. 212040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is recursive, but only go as deep as the number of include 212140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statements. 212222743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen return DoParse(source, include_paths, source_filename, include_filename); 212326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 212440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 212540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 212640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen break; 212726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 212840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 212940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Now parse all other kinds of declarations: 213040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != kTokenEof) { 213140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode) { 213240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 213340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenNameSpace) { 213440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 213540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == '{') { 213640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!root_struct_def_) 213740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("no root type set to parse json with"); 213840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (builder_.GetSize()) { 213940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot have more than one json object in a file"); 214094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 214140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t toff; 214240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 214340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.Finish(Offset<Table>(toff), 214440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 214540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenEnum) { 214640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, nullptr)); 214740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenUnion) { 214840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(true, nullptr)); 214940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenRootType) { 215040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 215140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto root_type = attribute_; 215240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 215340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&root_type, nullptr)); 215440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 215540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown root type: " + root_type); 215640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (root_struct_def_->fixed) 215740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("root type must be a table"); 215840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 215940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileIdentifier) { 216040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 216140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_ = attribute_; 216240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 216340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_identifier_.length() != 216440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 216540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("file_identifier must be exactly " + 216640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 216740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " characters"); 216840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 216940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileExtension) { 217040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 217140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_extension_ = attribute_; 217240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 217340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 217440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenInclude) { 217540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("includes must come before declarations"); 217640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenAttribute) { 217740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 217840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 217940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 218040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 218172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen known_attributes_[name] = false; 21821a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } else if (token_ == kTokenService) { 21831a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseService()); 218440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 218540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseDecl()); 218626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 218740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 218840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 218926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 219026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2191df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinezstd::set<std::string> Parser::GetIncludedFilesRecursive( 2192df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez const std::string &file_name) const { 2193df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::set<std::string> included_files; 2194df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::list<std::string> to_process; 2195df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2196df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (file_name.empty()) return included_files; 2197df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(file_name); 2198df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2199df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez while (!to_process.empty()) { 2200df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::string current = to_process.front(); 2201df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.pop_front(); 2202df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files.insert(current); 2203df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2204df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez auto new_files = files_included_per_file_.at(current); 2205df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez for (auto it = new_files.begin(); it != new_files.end(); ++it) { 2206df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (included_files.find(*it) == included_files.end()) 2207df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(*it); 2208df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2209df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2210df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2211df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez return included_files; 2212df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez} 2213df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 221481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Schema serialization functionality: 221581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 2216b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penketemplate<typename T> bool compareName(const T* a, const T* b) { 2217df0991b7ded0533554d3665e782273b6c8736376Xun Liu return a->defined_namespace->GetFullyQualifiedName(a->name) 2218df0991b7ded0533554d3665e782273b6c8736376Xun Liu < b->defined_namespace->GetFullyQualifiedName(b->name); 2219b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 2220b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 222181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssentemplate<typename T> void AssignIndices(const std::vector<T *> &defvec) { 222281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // Pre-sort these vectors, such that we can set the correct indices for them. 222381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto vec = defvec; 2224b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(vec.begin(), vec.end(), compareName<T>); 222581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 222681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 222781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 222881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenvoid Parser::Serialize() { 222981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Clear(); 223081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(structs_.vec); 223181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(enums_.vec); 223281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Object>> object_offsets; 223381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 223472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 223581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen object_offsets.push_back(offset); 223681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 223781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 223881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Enum>> enum_offsets; 223981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 224072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 224181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enum_offsets.push_back(offset); 224281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 224381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 224481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto schema_offset = reflection::CreateSchema( 224581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_, 224681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&object_offsets), 224781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&enum_offsets), 224881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_identifier_), 224981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_extension_), 225036c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen root_struct_def_ 225136c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen ? root_struct_def_->serialized_location 225236c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen : 0); 225381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 225481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 225581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 225672fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 225772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 225881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Field>> field_offsets; 225981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2260622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen field_offsets.push_back( 2261622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen (*it)->Serialize(builder, 226272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<uint16_t>(it - fields.vec.begin()), parser)); 226381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2264df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 226581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateObject(*builder, 2266df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 226781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVectorOfSortedTables( 226881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen &field_offsets), 2269cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen fixed, 2270cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen static_cast<int>(minalign), 227172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<int>(bytesize), 22721fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 22731fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 22741fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings( 22751fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen doc_comment) 22761fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 227781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 227881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 227981312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 228072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen uint16_t id, 228172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 228281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateField(*builder, 228381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 228481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.type.Serialize(builder), 228581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen id, 228681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.offset, 228781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsInteger(value.type.base_type) 228881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? StringToInt(value.constant.c_str()) 228981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0, 229081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsFloat(value.type.base_type) 229181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? strtod(value.constant.c_str(), nullptr) 229281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0.0, 229381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen deprecated, 229481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen required, 229572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen key, 22961fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 22971fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 22981fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 22991fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 230081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // TODO: value.constant is almost always "0", we could save quite a bit of 230181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // space by sharing it. Same for common values of value.type. 230281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 230381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 230472fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 230572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 230681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::EnumVal>> enumval_offsets; 230781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 230881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enumval_offsets.push_back((*it)->Serialize(builder)); 230981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2310df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 231181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnum(*builder, 2312df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 231381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVector(enumval_offsets), 231481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen is_union, 231572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen underlying_type.Serialize(builder), 23161fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 23171fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 23181fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 23191fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 232081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 232181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 232281312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const 232381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen { 232481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnumVal(*builder, 232581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 232681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value, 2327b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.struct_def 2328b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ? union_type.struct_def-> 2329b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen serialized_location 2330b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen : 0, 2331b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.Serialize(builder)); 233281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 233381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 233481312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 233581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateType(*builder, 233681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(base_type), 233781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(element), 233881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def ? struct_def->index : 233981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (enum_def ? enum_def->index : -1)); 234081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 234181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 234272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssenflatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< 234372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen reflection::KeyValue>>> 234472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen Definition::SerializeAttributes(FlatBufferBuilder *builder, 234572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 234672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2347e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 2348e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen auto it = parser.known_attributes_.find(kv->first); 234972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen assert(it != parser.known_attributes_.end()); 235072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (!it->second) { // Custom attribute. 235172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen attrs.push_back( 2352e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen reflection::CreateKeyValue(*builder, builder->CreateString(kv->first), 235372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen builder->CreateString( 2354e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen kv->second->constant))); 235572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 235672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 235772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (attrs.size()) { 235872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return builder->CreateVectorOfSortedTables(&attrs); 235972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } else { 236072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return 0; 236172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 236272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen} 236372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen 236405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssenstd::string Parser::ConformTo(const Parser &base) { 236505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 236605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &struct_def = **sit; 236705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 236805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 236905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto struct_def_base = base.structs_.Lookup(qualified_name); 237005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!struct_def_base) continue; 237105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fit = struct_def.fields.vec.begin(); 237205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fit != struct_def.fields.vec.end(); ++fit) { 237305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &field = **fit; 237405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto field_base = struct_def_base->fields.Lookup(field.name); 237505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field_base) { 237605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset != field_base->value.offset) 237705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "offsets differ for field: " + field.name; 237805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.constant != field_base->value.constant) 237905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "defaults differ for field: " + field.name; 238005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 238105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "types differ for field: " + field.name; 238205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } else { 238305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // Doesn't have to exist, deleting fields is fine. 238405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // But we should check if there is a field that has the same offset 238505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // but is incompatible (in the case of field renaming). 238605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fbit = struct_def_base->fields.vec.begin(); 238705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fbit != struct_def_base->fields.vec.end(); ++fbit) { 238805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen field_base = *fbit; 238905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset == field_base->value.offset) { 239005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 239105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "field renamed to different type: " + field.name; 239205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen break; 239305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 239405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 239505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 239605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 239705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 239805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 239905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_def = **eit; 240005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 240105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 240205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_def_base = base.enums_.Lookup(qualified_name); 240305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!enum_def_base) continue; 240405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto evit = enum_def.vals.vec.begin(); 240505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen evit != enum_def.vals.vec.end(); ++evit) { 240605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_val = **evit; 240705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 240805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val_base) { 240905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val.value != enum_val_base->value) 241005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "values differ for enum: " + enum_val.name; 241105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 241205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 241305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 241405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return ""; 241505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen} 241605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen 241726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 2418