idl_parser.cpp revision df0991b7ded0533554d3665e782273b6c8736376
126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen/* 226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Copyright 2014 Google Inc. All rights reserved. 326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Licensed under the Apache License, Version 2.0 (the "License"); 526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * you may not use this file except in compliance with the License. 626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * You may obtain a copy of the License at 726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * http://www.apache.org/licenses/LICENSE-2.0 926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 1026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Unless required by applicable law or agreed to in writing, software 1126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * distributed under the License is distributed on an "AS IS" BASIS, 1226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * See the License for the specific language governing permissions and 1426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * limitations under the License. 1526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen */ 1626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include <algorithm> 18df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez#include <list> 1926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#ifdef _WIN32 21d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#if !defined(_USE_MATH_DEFINES) 22d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#define _USE_MATH_DEFINES // For M_PI. 23d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // !defined(_USE_MATH_DEFINES) 24d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // _WIN32 25d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 26d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#include <math.h> 27d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 2826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/idl.h" 2926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/util.h" 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennamespace flatbuffers { 3226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char *const kTypeNames[] = { 3448dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 3548dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 3626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 3726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen nullptr 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char kTypeSizes[] = { 4248dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 43557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen sizeof(CTYPE), 4426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 4526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 4626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// The enums in the reflection schema should match the ones we use internally. 4981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Compare the last element to check if these go out of sync. 5081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenstatic_assert(BASE_TYPE_UNION == 51622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen static_cast<BaseType>(reflection::Union), 5281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen "enums don't match"); 5381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 54451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// Any parsing calls have to be wrapped in this macro, which automates 55451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// handling of recursive error checking a bit. It will check the received 56451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// CheckedError object, and return straight away on error. 5740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define ECHECK(call) { auto ce = (call); if (ce.Check()) return ce; } 58451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen 59451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// These two functions are called hundreds of times below, so define a short 60451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// form: 6140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define NEXT() ECHECK(Next()) 6240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define EXPECT(tok) ECHECK(Expect(tok)) 6340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 64f6416d847186802e03d2fa3c05963ec377c146fcBen Hamiltonstatic bool ValidateUTF8(const std::string &str) { 65f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char *s = &str[0]; 66f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char * const sEnd = s + str.length(); 67f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton while (s < sEnd) { 68f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (FromUTF8(&s) < 0) { 69f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return false; 70f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 71f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 72f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return true; 73f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton} 74f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton 7540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Error(const std::string &msg) { 7640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; 7740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #ifdef _WIN32 7840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += "(" + NumToString(line_) + ")"; // MSVC alike 7940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #else 8040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_being_parsed_.length()) error_ += ":"; 8140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += NumToString(line_) + ":0"; // gcc alike 8240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #endif 8340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += ": error: " + msg; 8440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return CheckedError(true); 8526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 8626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmersseninline CheckedError NoError() { return CheckedError(false); } 8840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 8926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 9040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::CheckBitsFit(int64_t val, size_t bits) { 913400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // Left-shifting a 64-bit value by 64 bits or more is undefined 923400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // behavior (C99 6.5.7), so check *before* we shift. 933400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield if (bits < 64) { 943400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield // Bits we allow to be used. 953400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield auto mask = static_cast<int64_t>((1ull << bits) - 1); 963400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield if ((val & ~mask) != 0 && // Positive or unsigned. 973400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield (val | mask) != -1) // Negative. 983400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield return Error("constant does not fit in a " + NumToString(bits) + 993400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield "-bit field"); 1003400727ffff0c0ab5b834632fea91948f7f43d66Ben Gertzfield } 10140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 10226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 10326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 10540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<typename T> inline CheckedError atot(const char *s, Parser &parser, 10640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen T *val) { 10740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t i = StringToInt(s); 10840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(parser.CheckBitsFit(i, sizeof(T) * 8)); 10940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = (T)i; 11040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<bool>(const char *s, Parser &parser, 11340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool *val) { 11440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 11540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = 0 != atoi(s); 11640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<float>(const char *s, Parser &parser, 11940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen float *val) { 12040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = static_cast<float>(strtod(s, nullptr)); 12240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 12440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<double>(const char *s, Parser &parser, 12540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen double *val) { 12640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = strtod(s, nullptr); 12840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 13240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Offset<void> *val) { 13340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = Offset<void>(atoi(s)); 13540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Namespace::GetFullyQualifiedName(const std::string &name, 13994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen size_t max_components) const { 14094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Early exit if we don't have a defined namespace. 14194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (components.size() == 0 || !max_components) { 14294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return name; 14394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 14494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::stringstream stream; 14594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t i = 0; i < std::min(components.size(), max_components); 14694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen i++) { 14794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (i) { 14894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "."; 14994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << components[i]; 15194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 15394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "." << name; 15494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return stream.str(); 15594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 15694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 15794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 15894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 15926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 16026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 16126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 16226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 16326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 16426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 16526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 16626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Identifier, 260, "identifier") \ 16726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Table, 261, "table") \ 16826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Struct, 262, "struct") \ 16926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Enum, 263, "enum") \ 17026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Union, 264, "union") \ 17126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(NameSpace, 265, "namespace") \ 1725da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(RootType, 266, "root_type") \ 1735da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(FileIdentifier, 267, "file_identifier") \ 174be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen TD(FileExtension, 268, "file_extension") \ 1750952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen TD(Include, 269, "include") \ 176049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen TD(Attribute, 270, "attribute") \ 1771a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen TD(Null, 271, "null") \ 1781a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen TD(Service, 272, "rpc_service") 1798f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 1808f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 1818f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 18226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 18375349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 18426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 18526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 18648dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 187557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen kToken ## ENUM, 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 18926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 19026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 19226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 19526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 19626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 19748dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 19848dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 2048e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 20526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 20626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 20726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 20926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 21026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 21194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Parser::TokenToStringId(int t) { 21294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return TokenToString(t) + (t == kTokenIdentifier ? ": " + attribute_ : ""); 21394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 21494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 215ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 21640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHexNum(int nibbles, int64_t *val) { 217ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 21830013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if (!isxdigit(static_cast<const unsigned char>(cursor_[i]))) 21940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("escape code must be followed by " + NumToString(nibbles) + 22040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " hex digits"); 2217cf74cb8644262f8ca02d69705bbc394d66514ceHiroshi Matsunaga std::string target(cursor_, cursor_ + nibbles); 22240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = StringToUInt(target.c_str(), 16); 223ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 22440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 225ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 226ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 227cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <OliCheckedError Parser::SkipByteOrderMark() { 228cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError(); 229cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli cursor_++; 230f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbb) return Error("invalid utf-8 byte order mark"); 231f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 232f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbf) return Error("invalid utf-8 byte order mark"); 233f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 234cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli return NoError(); 235cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli} 236cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli 237fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssenbool IsIdentifierStart(char c) { 238fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen return isalpha(static_cast<unsigned char>(c)) || c == '_'; 239fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen} 240fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen 24140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Next() { 24226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 24326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 24494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.clear(); 24526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 24626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 24726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 24826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 24940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return NoError(); 25026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 25240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': 25340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case ',': case ':': case ';': case '=': return NoError(); 25426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 25530013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError(); 25640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("floating point constant can\'t start with \".\""); 25726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 2586704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield case '\'': { 2596704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int unicode_high_surrogate = -1; 2606704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield 26194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != c) { 26226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 26340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character in string constant"); 26426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 26526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 2666704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1 && 2676704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield *cursor_ != 'u') { 2686704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2696704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 2706704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 27126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 27226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 27326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 27426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 275ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 276ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 27726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 27894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen case '\'': attribute_ += '\''; cursor_++; break; 27926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 280ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 281ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 282ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 28340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t val; 28440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(2, &val)); 28540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ += static_cast<char>(val); 286ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 287ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 288ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 289ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 29040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t val; 29140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(4, &val)); 2926704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (val >= 0xD800 && val <= 0xDBFF) { 2936704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 2946704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2956704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (multiple high surrogates)"); 2966704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 297e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen unicode_high_surrogate = static_cast<int>(val); 2986704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 2996704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else if (val >= 0xDC00 && val <= 0xDFFF) { 3006704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate == -1) { 3016704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3026704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired low surrogate)"); 3036704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3046704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int code_point = 0x10000 + 3056704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ((unicode_high_surrogate & 0x03FF) << 10) + 3066704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield (val & 0x03FF); 3076704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(code_point, &attribute_); 3086704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield unicode_high_surrogate = -1; 3096704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3106704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3116704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3126704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3136704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3146704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3156704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(static_cast<int>(val), &attribute_); 3166704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 317ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 318ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 31940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen default: return Error("unknown escape code in string constant"); 32026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 3226704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3236704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3246704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3256704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 32626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 32726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3296704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3306704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3316704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3326704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 334f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) { 335f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return Error("illegal UTF-8 sequence"); 336f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 33726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 33840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 3396704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 34026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 34126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 34226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 343a8d6962ac2fbf5075ee5f58877d488eb74ed32dfMormegil while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 34426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 34507d5965c812fa5e82dc4d3eb32b37540b7c91598Zbigniew Mandziejewicz if (cursor_ != source_ && !seen_newline) 34640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 34740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "a documentation comment should be on a line on its own"); 348730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez doc_comment_.push_back(std::string(start + 1, cursor_)); 34926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 35026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 35194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (*cursor_ == '*') { 35294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: make nested. 35494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != '*' || cursor_[1] != '/') { 35540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!*cursor_) return Error("end of file in comment"); 35694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 35894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_ += 2; 35994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen break; 36026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 36126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 36226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 363fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(c)) { 36426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 36526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 36626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 36726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 36826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 36926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 37026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // First, see if it is a type keyword from the table of types: 37148dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 37248dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 37326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == IDLTYPE) { \ 37426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kToken ## ENUM; \ 37540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); \ 37626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 37726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 37826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 37926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If it's a boolean constant keyword, turn those into integers, 38026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // which simplifies our logic downstream. 38126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "true" || attribute_ == "false") { 38226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ = NumToString(attribute_ == "true"); 38326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 38440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 38526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 38626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Check for declaration keywords: 38740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "table") { 38840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenTable; 38940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 39140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "struct") { 39240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenStruct; 39340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 39540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "enum") { 39640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenEnum; 39740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 39940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "union") { 40040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenUnion; 40140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "namespace") { 40440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenNameSpace; 40540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 40740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "root_type") { 40840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenRootType; 40940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "include") { 41240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenInclude; 41340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 41540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (attribute_ == "attribute") { 41640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen token_ = kTokenAttribute; 41740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 4195da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_identifier") { 4205da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileIdentifier; 42140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4225da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 4235da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_extension") { 4245da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileExtension; 42540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 4265da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 427049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (attribute_ == "null") { 428049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen token_ = kTokenNull; 429049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return NoError(); 430049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 4311a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (attribute_ == "rpc_service") { 4321a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen token_ = kTokenService; 4331a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 4341a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } 43526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If not, it is a user-defined identifier: 43626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 43740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 43826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 43926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 440f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman if (c == '-' && *cursor_ == '0' && (cursor_[1] == 'x' || cursor_[1] == 'X')) { 441f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++start; 442f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++cursor_; 443f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman attribute_.append(&c, &c + 1); 444f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman c = '0'; 445f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman } 44694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { 44794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 44894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 44994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.append(start + 2, cursor_); 4501917e577a23365508b08c7c8b082ab6a2a1ed6efWouter van Oortmerssen attribute_ = NumToString(StringToUInt(attribute_.c_str(), 16)); 45194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen token_ = kTokenIntegerConstant; 45240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 45394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 45426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 45594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.' || *cursor_ == 'e' || *cursor_ == 'E') { 45694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.') { 45794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 45894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 45994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 46093df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 46193df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 46293df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 46393df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 46493df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 46593df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 46693df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 46726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 46826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 46926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 47026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 47126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 47240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 47326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 47426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 47526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 47626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 47740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character: " + ch); 47826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 47926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 48026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 48126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 48240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen// Check if a given token is next. 48340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssenbool Parser::Is(int t) { 48440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return t == token_; 48526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 48626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 48726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 48840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Expect(int t) { 48926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 49040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("expecting: " + TokenToString(t) + " instead got: " + 49140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 49226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 49340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 49440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 49526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 49626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 49740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 49840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { 49940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 50039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += "."; 50139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += attribute_; 50239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen if (last) *last = attribute_; 50340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 50439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen } 50540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 50639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 50739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 50839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van OortmerssenEnumDef *Parser::LookupEnum(const std::string &id) { 50994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 51094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int components = static_cast<int>(namespaces_.back()->components.size()); 51194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components >= 0; components--) { 51240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto ed = enums_.Lookup( 51340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(id, components)); 51494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (ed) return ed; 51594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 51694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return nullptr; 51739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 51839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 51940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeIdent(Type &type) { 52039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen std::string id = attribute_; 52140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 52240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 52339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(id); 524d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def) { 525d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type = enum_def->underlying_type; 526d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 527d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 528d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 52939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen type.struct_def = LookupCreateStruct(id); 530d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 53140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 532d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 533d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 53426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 53540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseType(Type &type) { 53626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) { 53726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.base_type = static_cast<BaseType>(token_ - kTokenNONE); 53840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 53926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 54026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == kTokenIdentifier) { 54140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(type)); 54226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == '[') { 54340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 54426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type subtype; 54540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(subtype)); 54626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 54726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this, but it will complicate things, and it's 54826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // easier to work around with a struct around the inner vector. 54940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 55040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested vector types not supported (wrap in table first)."); 55126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 55226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_UNION) { 55326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this if we stored a struct of 2 elements per 55426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // union element. 55540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 55640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "vector of union types not supported (wrap in table first)."); 55726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 5583fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 55926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.element = subtype.base_type; 56040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 56126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 56240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal type syntax"); 56326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 56426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 56540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 56626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 56726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 56840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 56940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const Type &type, FieldDef **dest) { 57026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 57126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 57226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 57326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 574df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez field.file = struct_def.file; 57526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 57626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 57726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 57826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 57926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 58026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 58126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 58226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 5831256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 58426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 58526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 58626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 58740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field already exists: " + name); 58840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &field; 58940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 59026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 59126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 59240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseField(StructDef &struct_def) { 59326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 594730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez std::vector<std::string> dc = doc_comment_; 59540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 59640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(':'); 59726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 59840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(type)); 59926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 60026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 60140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("structs_ may contain only scalar or struct fields"); 60226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 60426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 60526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 6069e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // with a special suffix. 6079e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 6089e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type.enum_def->underlying_type, &typefield)); 60926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 61026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 61140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field; 61240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(AddField(struct_def, name, type, &field)); 61326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 61426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 61540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 61615dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 61740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("default values currently only supported for scalars"); 61840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(field->value)); 619fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen } 620fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (IsFloat(field->value.type.base_type)) { 621fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (!strpbrk(field->value.constant.c_str(), ".eE")) 622fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen field->value.constant += ".0"; 62326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 62426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6257b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen if (type.enum_def && 6267b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen IsScalar(type.base_type) && 6277b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !struct_def.fixed && 6287b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !type.enum_def->attributes.Lookup("bit_flags") && 629d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen !type.enum_def->ReverseLookup(static_cast<int>( 63040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StringToInt(field->value.constant.c_str())))) 63140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum " + type.enum_def->name + 6327b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen " does not have a declaration for this field\'s default of " + 63340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant); 6347b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen 63540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = dc; 636e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&field->attributes)); 63740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 63840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto hash_name = field->attributes.Lookup("hash"); 639d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (hash_name) { 640d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (type.base_type) { 641d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 642d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 643d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 64440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 32 bit types: " + 645d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 646d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 647d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 648d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 649d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 650d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 65140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 64 bit types: " + 652d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 653d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 654d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 655d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 65640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 65740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "only int, uint, long and ulong data types support hashing."); 658d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 659d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 66040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->deprecated && struct_def.fixed) 66140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("can't deprecate fields in a struct"); 66240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = field->attributes.Lookup("required") != nullptr; 66340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->required && (struct_def.fixed || 66440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(field->value.type.base_type))) 66540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only non-scalar fields in tables may be 'required'"); 66640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->key = field->attributes.Lookup("key") != nullptr; 66740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->key) { 6683550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen if (struct_def.has_key) 66940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only one field may be set as 'key'"); 6703550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen struct_def.has_key = true; 67140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(field->value.type.base_type)) { 67240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = true; 67340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_STRING) 67440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("'key' field must be string or scalar type"); 6753550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 6763550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 67740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto nested = field->attributes.Lookup("nested_flatbuffer"); 6783e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 6793e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 68040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 68140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute must be a string (the root type)"); 68240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 68340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 68440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 68540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute may only apply to a vector of ubyte"); 6863e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 6873e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 6883e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 6893e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 69026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6919140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 6929140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 6939140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 69440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto attr = field->attributes.Lookup("id"); 6959140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 6969140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 6979140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 6989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 6999140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 7009140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 7019140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 70440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 70540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 70626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 70726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 70840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 7099e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen size_t parent_fieldn, 7109e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen const StructDef *parent_struct_def) { 71126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 71226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 71326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 7149e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen std::string constant; 7154d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen if (!parent_fieldn || 7169e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen field_stack_.back().second->value.type.base_type != BASE_TYPE_UTYPE) { 7179e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // We haven't seen the type field yet. Sadly a lot of JSON writers 7189e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // output these in alphabetical order, meaning it comes after this 7199e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // value. So we scan past the value to find it, then come back here. 7209e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_name = field->name + UnionTypeFieldSuffix(); 7219e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(parent_struct_def); 7229e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_field = parent_struct_def->fields.Lookup(type_name); 7239e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(type_field); // Guaranteed by ParseField(). 7249e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Remember where we are in the source file, so we can come back here. 7259e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto backup = *static_cast<ParserState *>(this); 7269e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(SkipAnyJsonValue()); // The table. 7279e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(','); 7289e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto next_name = attribute_; 7299e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (Is(kTokenStringConstant)) { 7309e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen NEXT(); 7319e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7329e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(kTokenIdentifier); 7339e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 7349e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (next_name != type_name) 7359e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen return Error("missing type field after this union value: " + 7369e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type_name); 7379e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(':'); 7389e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen Value type_val = type_field->value; 7399e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 7409e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = type_val.constant; 7419e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Got the information we needed, now rewind: 7429e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen *static_cast<ParserState *>(this) = backup; 7439e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7449e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = field_stack_.back().first.constant; 7459e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 74640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uint8_t enum_idx; 7479e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(atot(constant.c_str(), *this, &enum_idx)); 7483fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 74940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("illegal type id for: " + field->name); 75040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr)); 75126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 75226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 75326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 75440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 75526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 75626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 75726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto s = attribute_; 75840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 75926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 76026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 76126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 76226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 76340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('['); 76440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t off; 76540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseVector(val.type.VectorType(), &off)); 76640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val.constant = NumToString(off); 76726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 76826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 769d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 770d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: 771d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 772d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 773d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (field && field->attributes.Lookup("hash") && 774d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 77540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHash(val, field)); 776d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } else { 77740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 778d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 779d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 780d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 78126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 78240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 78326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 78426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 78540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 78626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 78726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 78826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 7894d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(val.constant.length() == struct_def.bytesize); 79026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 7914d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 7924d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 79326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 79426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 79526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 79640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 79740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t *ovalue) { 79840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 79926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size_t fieldn = 0; 8006c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 80140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((!opts.strict_json || !fieldn) && Is('}')) { NEXT(); break; } 80226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 80340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenStringConstant)) { 80440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 80540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 80640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 80740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 80826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = struct_def.fields.Lookup(name); 80913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!field) { 81013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!opts.skip_unexpected_fields_in_json) { 81113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return Error("unknown field: " + name); 81213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 81313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 81413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 81513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 81613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 81713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 818049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (Is(kTokenNull)) { 819049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen NEXT(); // Ignore this field. 820049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } else { 821049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen Value val = field->value; 8229e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(val, field, fieldn, &struct_def)); 823049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen size_t i = field_stack_.size(); 824049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // Hardcoded insertion-sort with error-check. 825049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // If fields are specified in order, then this loop exits immediately. 826049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen for (; i > field_stack_.size() - fieldn; i--) { 827049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen auto existing_field = field_stack_[i - 1].second; 828049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field == field) 829049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen return Error("field set more than once: " + field->name); 830049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field->value.offset < field->value.offset) break; 831049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 832049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen field_stack_.insert(field_stack_.begin() + i, std::make_pair(val, field)); 833049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen fieldn++; 83413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 8354d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen } 83640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) { NEXT(); break; } 83740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 83826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 83913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 84026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && fieldn != struct_def.fields.vec.size()) 84140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("struct: wrong number of initializers: " + struct_def.name); 8424d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen 84326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 84426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 84526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 84626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 84726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 84826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 84926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 85026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 85126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = field_stack_.rbegin(); 85226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 853721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma auto &field_value = it->first; 85426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 85540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.sortbysize || 85640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen size == SizeOf(field_value.type.base_type)) { 857721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma switch (field_value.type.base_type) { 85848dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 85948dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 86026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 86126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 862be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 86340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 86440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 86540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(val); \ 866be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 86740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val, valdef; \ 86840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 86940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 87040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddElement(field_value.offset, val, valdef); \ 871be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 87226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 87326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 87426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 87548dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 87648dfc69ee613a176f13b04c2310adb7a08fe6737rw PTYPE) \ 87726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 87826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 87926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 880721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma SerializeStruct(*field->value.type.struct_def, field_value); \ 88126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 88240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 88340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 88440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddOffset(field_value.offset, val); \ 88526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 88626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 88726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 88826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 88926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 89026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 89126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 89226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 89326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t i = 0; i < fieldn; i++) field_stack_.pop_back(); 89426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 89526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 89626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 89726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 8984d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(value); 8994d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // Temporarily store this struct in the value string, since it is to 9004d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // be serialized in-place elsewhere. 9014d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen value->assign( 9024d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 9034d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 90426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 90540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen assert(!ovalue); 90626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 90740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto val = builder_.EndTable(start, 90840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen static_cast<voffset_t>(struct_def.fields.vec.size())); 90940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (ovalue) *ovalue = val; 91040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (value) *value = NumToString(val); 91126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 91240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 91326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 91426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 91540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 91626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int count = 0; 9176c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 91840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((!opts.strict_json || !count) && Is(']')) { NEXT(); break; } 91926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 92026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.type = type; 9219e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(val, nullptr, 0, nullptr)); 92226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.push_back(std::make_pair(val, nullptr)); 92326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen count++; 92440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(']')) { NEXT(); break; } 92540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 92626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 92726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 928be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 929be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 93026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (int i = 0; i < count; i++) { 93126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 93226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 93326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 93448dfc69ee613a176f13b04c2310adb7a08fe6737rw #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 93526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 93626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 93740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen else { \ 93840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE elem; \ 93940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 94040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(elem); \ 94140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } \ 94226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 94326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 94426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 94526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 94626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 94726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 94826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 94926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 95040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *ovalue = builder_.EndVector(count); 95140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 95226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 95326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 954e6b79f00022aee3108427977c9823ff57154e1c6Wouter van OortmerssenCheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 95540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('(')) { 95640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 95726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 95826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 95940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 9600952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen if (known_attributes_.find(name) == known_attributes_.end()) 96140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("user define attributes must be declared before use: " + 96240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen name); 96326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 964e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen attributes->Add(name, e); 96540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(':')) { 96640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 96740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(*e)); 96826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(')')) { NEXT(); break; } 97040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 97126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 97226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 97340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 97426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 97526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 97640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e, 97740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BaseType req, bool *destmatch) { 97826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 97926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 98040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *destmatch = true; 98126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 98226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 98326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 98426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 98526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 98640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error(std::string("type mismatch: expecting: ") + 98740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[e.type.base_type] + 98840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ", found: " + 98940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[req]); 99026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 99126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 99240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 99326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 99440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 99526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 99626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 997fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van OortmerssenCheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 99840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result = 0; 9999c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 10009c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 10019c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 10029c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 10039c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 10049c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 10059c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 10069c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 10079c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 10089c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 10099c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 10109c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 10119c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 10129c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 10139c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 101440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown enum value: " + word + 10159c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 101640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 10179c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 10189c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 101940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("not a valid value for this field: " + word); 10209c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 102139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen const char *dot = strrchr(word.c_str(), '.'); 102240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!dot) 102340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values need to be qualified by an enum type"); 10249c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 10259c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 102639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(enum_def_str); 102740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_def) return Error("unknown enum: " + enum_def_str); 10289c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 102940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("unknown enum value: " + enum_val_str); 103040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 10319c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 10329c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 103340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 10349c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 10359c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 1036d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 103740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHash(Value &e, FieldDef* field) { 1038d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(field); 1039d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames Value *hash_name = field->attributes.Lookup("hash"); 1040d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (e.type.base_type) { 1041d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 1042d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 1043d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction32(hash_name->constant.c_str()); 1044d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint32_t hashed_value = hash(attribute_.c_str()); 1045d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1046d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1047d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1048d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 1049d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 1050d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction64(hash_name->constant.c_str()); 1051d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint64_t hashed_value = hash(attribute_.c_str()); 1052d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1053d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1054d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1055d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 1056d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(0); 1057d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 105840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 105940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1060d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames} 1061d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 106240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseSingleValue(Value &e) { 1063d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // First see if this could be a conversion function: 1064d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (token_ == kTokenIdentifier && *cursor_ == '(') { 1065d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto functionname = attribute_; 1066d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen NEXT(); 1067d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT('('); 1068d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen ECHECK(ParseSingleValue(e)); 1069d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT(')'); 1070d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1071d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (functionname == name) { \ 1072d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto x = strtod(e.constant.c_str(), nullptr); \ 1073d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen e.constant = NumToString(op); \ 1074d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } 1075d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("deg", x / M_PI * 180); 1076d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("rad", x * M_PI / 180); 1077d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1078d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1079d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1080d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1081d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1082d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1083d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // TODO(wvo): add more useful conversion functions here. 1084d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #undef FLATBUFFERS_FN_DOUBLE 1085d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // Then check if this could be a string/identifier enum value: 1086d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } else if (e.type.base_type != BASE_TYPE_STRING && 10879c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 10889c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 1089fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(attribute_[0])) { // Enum value. 1090fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen int64_t val; 1091fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen ECHECK(ParseEnumFromString(e.type, &val)); 1092fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(val); 1093fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen NEXT(); 1094fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { // Numeric constant in string. 1095fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsInteger(e.type.base_type)) { 1096fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen // TODO(wvo): do we want to check for garbage after the number? 1097fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(StringToInt(attribute_.c_str())); 1098fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else if (IsFloat(e.type.base_type)) { 1099fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(strtod(attribute_.c_str(), nullptr)); 1100fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { 1101fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen assert(0); // Shouldn't happen, we covered all types. 1102fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = "0"; 1103fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 110483dc5ed4a7267c78fb3f00e972de4db30762166dWouter van Oortmerssen NEXT(); 1105fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 110626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 110740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool match = false; 110840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenIntegerConstant, 110940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(e.type.base_type), 111040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 111140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_INT, 111240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 111340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenFloatConstant, 111440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsFloat(e.type.base_type), 111540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 111640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_FLOAT, 111740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 111840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenStringConstant, 111940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 112040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 112140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_STRING, 112240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 112340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!match) 112440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot parse value starting with: " + 112540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 112626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 112740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 112826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 112926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 113094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name, 113194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool create_if_new, bool definition) { 113294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string qualified_name = namespaces_.back()->GetFullyQualifiedName(name); 113320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an unqualified use. 113494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto struct_def = structs_.Lookup(name); 113594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 113694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 113720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace, and is registered under its 113820c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // qualified name. 113994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 114094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Move(name, qualified_name); 114194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 114294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return struct_def; 114394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 114420c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an qualified use. 114594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup(qualified_name); 114620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 114720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (definition) { 114820c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace. 114920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 115020c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 115120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen return struct_def; 115220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 115394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!definition) { 115494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 115594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t components = namespaces_.back()->components.size(); 115694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components && !struct_def; components--) { 115794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup( 115894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name, components - 1)); 115994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 116094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 116194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!struct_def && create_if_new) { 116226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 116394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 116494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(qualified_name, struct_def); 116594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 116694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 116794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 116894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Not a definition. 116994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 117094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 117194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // It is defined in the root namespace, since we don't know what the 117294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // final namespace will be. 117394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: maybe safer to use special namespace? 117494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(name, struct_def); 117594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 117694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->defined_namespace = new Namespace(); 117794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), struct_def->defined_namespace); 117894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 117926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 118026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 118126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 118226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 118340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1184c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::vector<std::string> enum_comment = doc_comment_; 118540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1186c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::string enum_name = attribute_; 118740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 118826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 1189c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.name = enum_name; 119040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen enum_def.file = file_being_parsed_; 1191c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.doc_comment = enum_comment; 119226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 11937b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen enum_def.defined_namespace = namespaces_.back(); 119494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enums_.Add(namespaces_.back()->GetFullyQualifiedName(enum_name), 119594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen &enum_def)) 119640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum already exists: " + enum_name); 119726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 119826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 119926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 1200a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 120145bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode) { 120294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_INT; 1203d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 1204d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Give specialized error message, since this type spec used to 1205d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // be optional in the first FlatBuffers release. 120640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(':')) { 120740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("must specify the underlying integer type for this" 120840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 120940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 121040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 121140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 1212d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Specify the integer type underlying this enum. 121340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(enum_def.underlying_type)); 1214d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 121540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("underlying enum type must be integral"); 1216d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 12173fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 12183fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 121926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1220e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&enum_def.attributes)); 122140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 122226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 122340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 122445bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode && attribute_ == "option") { 122540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 122694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 122794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value_name = attribute_; 122894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto full_name = value_name; 122994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> value_comment = doc_comment_; 123040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 12313639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen if (is_union) { 12323639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen ECHECK(ParseNamespacing(&full_name, &value_name)); 1233d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen if (opts.union_value_namespacing) { 1234d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // Since we can't namespace the actual enum identifiers, turn 1235d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // namespace parts into part of the identifier. 1236d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen value_name = full_name; 1237d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen std::replace(value_name.begin(), value_name.end(), '.', '_'); 1238d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen } 12393639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen } 124094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 124194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value = enum_def.vals.vec.size() 124294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 124394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen : 0; 124494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &ev = *new EnumVal(value_name, value); 124594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enum_def.vals.Add(value_name, &ev)) 124640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum value already exists: " + value_name); 124794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.doc_comment = value_comment; 124894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (is_union) { 124994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.struct_def = LookupCreateStruct(full_name); 125094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 125140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('=')) { 125240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1253d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen ev.value = StringToInt(attribute_.c_str()); 125440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 125545bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (!opts.proto_mode && prevsize && 125694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.vals.vec[prevsize - 1]->value >= ev.value) 125740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values must be specified in ascending order"); 125894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 125940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && Is('[')) { 126040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 126194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // ignore attributes on enums. 126240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != ']') NEXT(); 126340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 126494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 126526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 126640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(opts.proto_mode ? ';' : ',')) break; 126740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 126840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) break; 126940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 127040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1271127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 1272127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1273127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 1274127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 1275127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 127640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("bit flag out of range of underlying integral type"); 12779c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 1278127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 1279127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 128040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (dest) *dest = &enum_def; 128140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 128226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 128326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 128440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 128594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name, true, true); 128640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.predecl) return Error("datatype already exists: " + name); 128726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 128826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 128940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def.file = file_being_parsed_; 129026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 1291d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // to preserve declaration order. 12923b070310f03326597666babf6654aa983d063bb2Wouter van Oortmerssen *remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; 129340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &struct_def; 129440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1295d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1296d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1297b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra PenkeCheckedError Parser::CheckClash(std::vector<FieldDef*> &fields, 1298b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke StructDef *struct_def, 1299b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke const char *suffix, 1300b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke BaseType basetype) { 1301b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto len = strlen(suffix); 1302b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke for (auto it = fields.begin(); it != fields.end(); ++it) { 1303b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto &fname = (*it)->name; 1304b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (fname.length() > len && 1305b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.compare(fname.length() - len, len, suffix) == 0 && 1306b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1307b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto field = struct_def->fields.Lookup( 1308b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.substr(0, fname.length() - len)); 1309b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (field && field->value.type.base_type == basetype) 1310b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return Error("Field " + fname + 1311b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke " would clash with generated functions for field " + 1312b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke field->name); 1313b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1314b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1315b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return NoError(); 1316b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1317d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen 1318b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1319b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1320b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1321b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a_id < b_id; 1322b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1323b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 132440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseDecl() { 1325d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen std::vector<std::string> dc = doc_comment_; 132640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool fixed = Is(kTokenStruct); 132740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (fixed) NEXT() else EXPECT(kTokenTable); 132894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 132940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 133040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StructDef *struct_def; 133140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 133240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->doc_comment = dc; 133340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->fixed = fixed; 1334e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&struct_def->attributes)); 133540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->sortbysize = 133640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 133740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 133840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != '}') ECHECK(ParseField(*struct_def)); 133940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto force_align = struct_def->attributes.Lookup("force_align"); 134026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 134126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 134226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 134340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen align < struct_def->minalign || 134445cc503bbdad33849c62d11e152fab2f852892dbWouter van Oortmerssen align > 16 || 134526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 134640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("force_align must be a power of two integer ranging from the" 134745cc503bbdad33849c62d11e152fab2f852892dbWouter van Oortmerssen "struct\'s natural alignment to 16"); 134840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->minalign = align; 134926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 135040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->PadLastField(struct_def->minalign); 13519140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 135240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &fields = struct_def->fields.vec; 135340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def->fixed && fields.size()) { 13547fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 13559140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 13569140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 13579140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 13589140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 13599140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 13609140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 13619140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 136240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 136340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "either all fields or no fields must have an 'id' attribute"); 13649140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 13659140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 1366b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(fields.begin(), fields.end(), compareFieldDefs); 13679140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 13689140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 13699140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 137040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field id\'s must be consecutive from 0, id " + 13719140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 13729140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 13739140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 13749140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 13759140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 1376b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 13779e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), 13789e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen BASE_TYPE_UNION)); 1379b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1380b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1381b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1382b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1383b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 138440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 138540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 138626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 138726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 13881a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van OortmerssenCheckedError Parser::ParseService() { 13891a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen std::vector<std::string> service_comment = doc_comment_; 13901a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 13911a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto service_name = attribute_; 13921a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 13931a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &service_def = *new ServiceDef(); 13941a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.name = service_name; 13951a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.file = file_being_parsed_; 13961a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.doc_comment = service_comment; 13971a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.defined_namespace = namespaces_.back(); 13981a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (services_.Add(namespaces_.back()->GetFullyQualifiedName(service_name), 13991a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen &service_def)) 14001a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("service already exists: " + service_name); 1401e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&service_def.attributes)); 14021a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('{'); 14031a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen do { 14041a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto rpc_name = attribute_; 14051a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14061a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('('); 14071a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen Type reqtype, resptype; 14081a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(reqtype)); 14091a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(')'); 14101a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(':'); 14111a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(resptype)); 14121a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 14131a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 14141a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc request and response types must be tables"); 14151a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &rpc = *new RPCCall(); 14161a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.name = rpc_name; 14171a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.request = reqtype.struct_def; 14181a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.response = resptype.struct_def; 14191a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (service_def.calls.Add(rpc_name, &rpc)) 14201a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc already exists: " + rpc_name); 1421e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&rpc.attributes)); 14221a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(';'); 14231a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } while (token_ != '}'); 14241a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 14251a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 14261a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen} 14271a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen 142826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 14294dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup(name); 14304dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen if (!root_struct_def_) 14314dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup( 14324dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen namespaces_.back()->GetFullyQualifiedName(name)); 143381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return root_struct_def_ != nullptr; 143426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 143526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1436be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 14373881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // This function marks all existing definitions as having already 14383881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // been generated, which signals no code for included files should be 14393881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // generated. 1440be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 1441be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 1442be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1443be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 1444be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 1445be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 1446be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1447be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 144848f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen for (auto it = services_.vec.begin(); 144948f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen it != services_.vec.end(); ++it) { 145048f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen (*it)->generated = true; 145148f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen } 1452be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 1453be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 145440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespace() { 145540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1456d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen auto ns = new Namespace(); 1457d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen namespaces_.push_back(ns); 145894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ != ';') { 145994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (;;) { 146094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(attribute_); 146140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 146240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT() else break; 146394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1464d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 146540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 146640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1467d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1468d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1469b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareEnumVals(const EnumVal *a, const EnumVal* b) { 1470b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a->value < b->value; 1471b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1472b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 1473d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Best effort parsing of .proto declarations, with the aim to turn them 1474d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// in the closest corresponding FlatBuffer equivalent. 1475d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// We parse everything as identifiers instead of keywords, since we don't 1476d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// want protobuf keywords to become invalid identifiers in FlatBuffers. 147740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoDecl() { 147894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool isextend = attribute_ == "extend"; 1479d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == "package") { 1480d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // These are identical in syntax to FlatBuffer's namespace decl. 148140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 148294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "message" || isextend) { 14833ad853630c6bf76a9c8fc2a15e3fc40cd52de691Advay Mengle std::vector<std::string> struct_comment = doc_comment_; 148440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 148594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *struct_def = nullptr; 148694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 148740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 148894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto id = attribute_; 148940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 149040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 149194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = LookupCreateStruct(id, false); 149240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def) 149340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot extend unknown message type: " + id); 149494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 149594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 149640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 149740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 149894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Since message definitions can be nested, we create a new namespace. 149994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = new Namespace(); 150094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Copy of current namespace. 150194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen *ns = *namespaces_.back(); 150294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // But with current message name. 150394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(name); 150494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(ns); 150594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 150694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->doc_comment = struct_comment; 150740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(struct_def, isextend, false)); 150894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!isextend) { 150994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We have to remove the nested namespace, but we can't just throw it 151094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // away, so put it at the beginning of the vector. 151194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = namespaces_.back(); 151294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.pop_back(); 151394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.insert(namespaces_.begin(), ns); 151494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 151540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 151694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "enum") { 151794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // These are almost the same, just with different terminator: 151840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EnumDef *enum_def; 151940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, &enum_def)); 152040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 152194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protobuf allows them to be specified in any order, so sort afterwards. 152240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &v = enum_def->vals.vec; 1523d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen std::sort(v.begin(), v.end(), compareEnumVals); 1524b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 152594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: remove any duplicates, as .fbs files can't handle them. 152694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (auto it = v.begin(); it != v.end(); ) { 152794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it); 152894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else ++it; 152994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 153094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "syntax") { // Skip these. 153140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 153240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 153340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 153440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 153594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 153640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 153740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 153894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "service") { // Skip these. 153940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 154040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 154140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 154294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 154340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("don\'t know how to parse .proto declaration starting with " + 154494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen TokenToStringId(token_)); 154594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 154640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 154794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 154894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 154940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 155040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool inside_oneof) { 155140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 155294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (token_ != '}') { 155394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "message" || attribute_ == "extend" || 155494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_ == "enum") { 155594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Nested declarations. 155640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 155794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "extensions") { // Skip these. 155840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 155940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 156040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenIdentifier)) { 156140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // to 156240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // num 156394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 156440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 156594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "option") { // Skip these. 156640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 156740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 156894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "reserved") { // Skip these. 156940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 157040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 157140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } 157240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 157394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 157494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> field_comment = doc_comment_; 157594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Parse the qualifier. 157694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool required = false; 157794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool repeated = false; 157894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool oneof = false; 157994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!inside_oneof) { 15802abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen if (attribute_ == "optional") { 15812abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // This is the default. 158240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 15832abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "required") { 15842abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen required = true; 158540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 15862abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else if (attribute_ == "repeated") { 15872abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen repeated = true; 158840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 158994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (attribute_ == "oneof") { 159094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen oneof = true; 159140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 15922abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else { 159394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // can't error, proto3 allows decls without any of the above. 15942abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } 159594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 159694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *anonymous_struct = nullptr; 159794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen Type type; 159894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (attribute_ == "group" || oneof) { 159940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!oneof) EXPECT(kTokenIdentifier); 160094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto name = "Anonymous" + NumToString(anonymous_counter++); 160140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &anonymous_struct)); 160294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type = Type(BASE_TYPE_STRUCT, anonymous_struct); 160394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 160440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeFromProtoType(&type)); 160594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 160694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Repeated elements get mapped to a vector. 160794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (repeated) { 160894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.element = type.base_type; 160994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.base_type = BASE_TYPE_VECTOR; 161094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 161194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 161294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protos may use our keywords "attribute" & "namespace" as an identifier. 161340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenAttribute) || Is(kTokenNameSpace)) { 161440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 161594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: simpler to just not make these keywords? 161694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen name += "_"; // Have to make it not a keyword. 161794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 161840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 161994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 162094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!oneof) { 16212abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // Parse the field id. Since we're just translating schemas, not 16222abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // any kind of binary compatibility, we can safely ignore these, and 16232abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // assign our own. 162440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 162540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 162694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 162740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field = nullptr; 162894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 162994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We allow a field to be re-defined when extending. 163094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: are there situations where that is problematic? 163140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field = struct_def->fields.Lookup(name); 163294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 163340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 163440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = field_comment; 163540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(type.base_type)) field->required = required; 163694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // See if there's a default specified. 163740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('[')) { 163840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 163940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 164094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto key = attribute_; 164140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 164240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 164394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto val = attribute_; 164440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 164594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (key == "default") { 164694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: skip non-numeric defaults (enums). 164794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto numeric = strpbrk(val.c_str(), "0123456789-+."); 164894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (IsScalar(type.base_type) && numeric == val.c_str()) 164940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant = val; 165094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (key == "deprecated") { 165140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = val == "true"; 165294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 165340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(',')) break; 165440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 165540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 165640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 165794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 165894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (anonymous_struct) { 165940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 166040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 166194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 166240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 1663d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1664d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 166594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 166640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 166740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 166894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 166994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 167040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoKey() { 167194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '(') { 167240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 167394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Skip "(a.b)" style custom attributes. 167440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 167540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(')'); 167640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { NEXT(); EXPECT(kTokenIdentifier); } 167794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 167840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 167994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 168040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 168194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 168294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 168340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoCurliesOrIdent() { 168440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('{')) { 168540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 168694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int nesting = 1; nesting; ) { 168794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '{') nesting++; 168894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else if (token_ == '}') nesting--; 168940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 169094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1691d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 169240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // Any single token. 1693d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 169440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1695d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1696d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 169740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoOption() { 169840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 169940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 170040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 170140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 170240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 170394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 170494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 1705d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Parse a protobuf type, and map it to the corresponding FlatBuffer one. 170640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeFromProtoType(Type *type) { 1707d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen struct type_lookup { const char *proto_type; BaseType fb_type; }; 1708d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen static type_lookup lookup[] = { 1709d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "float", BASE_TYPE_FLOAT }, { "double", BASE_TYPE_DOUBLE }, 1710d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "int32", BASE_TYPE_INT }, { "int64", BASE_TYPE_LONG }, 1711d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "uint32", BASE_TYPE_UINT }, { "uint64", BASE_TYPE_ULONG }, 1712d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sint32", BASE_TYPE_INT }, { "sint64", BASE_TYPE_LONG }, 1713d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "fixed32", BASE_TYPE_UINT }, { "fixed64", BASE_TYPE_ULONG }, 1714d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "sfixed32", BASE_TYPE_INT }, { "sfixed64", BASE_TYPE_LONG }, 1715d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bool", BASE_TYPE_BOOL }, 1716d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "string", BASE_TYPE_STRING }, 1717d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { "bytes", BASE_TYPE_STRING }, 1718d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen { nullptr, BASE_TYPE_NONE } 1719d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen }; 1720d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen for (auto tl = lookup; tl->proto_type; tl++) { 1721d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == tl->proto_type) { 172240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen type->base_type = tl->fb_type; 172340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 172440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1725d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1726d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 172740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 172840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(*type)); 172940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1730d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1731d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 173213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipAnyJsonValue() { 173313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke switch (token_) { 173413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case '{': 173513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonObject()); 173613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 173713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenStringConstant: 173813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonString()); 173913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 174013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case '[': 174113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipJsonArray()); 174213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 174313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenIntegerConstant: 174413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenIntegerConstant); 174513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 174613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenFloatConstant: 174713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenFloatConstant); 174813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke break; 174913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke default: 1750e0b2f81885b09ffba4ec89bfd2c9796d3be01865Chris Pickett return Error(std::string("Unexpected token:") + std::string(1, static_cast<char>(token_))); 175113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 175213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 175313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 175413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 175513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonObject() { 175613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT('{'); 175713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke size_t fieldn = 0; 175813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 17590e1601b80de3c69cf49894d58840856f2077731bChris Pickett for (;;) { 176013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if ((!opts.strict_json || !fieldn) && Is('}')) break; 176113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 1762cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke if (!Is(kTokenStringConstant)) { 176313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 1764cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 1765cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke else { 1766cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke NEXT(); 1767cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 176813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 176913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(':'); 177013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 177113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke fieldn++; 177213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 177313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is('}')) break; 177413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(','); 177513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 177613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 177713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke NEXT(); 177813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 177913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 178013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 178113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonArray() { 178213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT('['); 1783049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen 17840e1601b80de3c69cf49894d58840856f2077731bChris Pickett for (;;) { 178513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is(']')) break; 1786049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen 178713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke ECHECK(SkipAnyJsonValue()); 178813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 178913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (Is(']')) break; 179013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(','); 179113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 179213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 179313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke NEXT(); 179413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 179513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 179613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 179713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipJsonString() { 179813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke EXPECT(kTokenStringConstant); 179913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 180013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 180113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 180230642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths, 180330642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen const char *source_filename) { 180440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return !DoParse(source, include_paths, source_filename).Check(); 180540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen} 180640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 180740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::DoParse(const char *source, const char **include_paths, 180840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const char *source_filename) { 180940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_being_parsed_ = source_filename ? source_filename : ""; 1810df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (source_filename && 1811df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files_.find(source_filename) == included_files_.end()) { 1812df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files_[source_filename] = true; 1813df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez files_included_per_file_[source_filename] = std::set<std::string>(); 1814df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 1815df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (!include_paths) { 18161e6f8f5b8c4d0407d7db750858e7863e07091958Wouter van Oortmerssen static const char *current_directory[] = { "", nullptr }; 1817df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez include_paths = current_directory; 1818df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 181926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen source_ = cursor_ = source; 182026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen line_ = 1; 182126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen error_.clear(); 182226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 182394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Start with a blank namespace just in case this file doesn't have one. 182494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen namespaces_.push_back(new Namespace()); 1825cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli ECHECK(SkipByteOrderMark()); 182640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 182740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Includes must come before type declarations: 182840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 182940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Parse pre-include proto statements if any: 183040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && 183140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (attribute_ == "option" || attribute_ == "syntax" || 183240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "package")) { 183340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 183440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (Is(kTokenInclude) || 183540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (opts.proto_mode && 183640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "import" && 183740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Is(kTokenIdentifier))) { 183840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 183940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && attribute_ == "public") NEXT(); 184040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 184140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 184240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Look for the file in include_paths. 184340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string filepath; 184440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 184540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen filepath = flatbuffers::ConCatPathFileName(*paths, name); 184640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if(FileExists(filepath.c_str())) break; 1847be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 184840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (filepath.empty()) 184940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to locate include file: " + name); 185040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (source_filename) 185140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen files_included_per_file_[source_filename].insert(filepath); 185240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (included_files_.find(filepath) == included_files_.end()) { 185340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We found an include file that we have not parsed yet. 185440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Load it and parse it. 185540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string contents; 185640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!LoadFile(filepath.c_str(), true, &contents)) 185740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to load include file: " + name); 185840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str())); 185940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We generally do not want to output code for any included files: 186040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!opts.generate_all) MarkGenerated(); 186140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is the easiest way to continue this file after an include: 186240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 186340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // file anew. This will cause it to encounter the same include 186440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statement again, but this time it will skip it, because it was 186540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // entered into included_files_. 186640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is recursive, but only go as deep as the number of include 186740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statements. 186840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return DoParse(source, include_paths, source_filename); 186926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 187040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 187140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 187240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen break; 187326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 187440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 187540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Now parse all other kinds of declarations: 187640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != kTokenEof) { 187740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode) { 187840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 187940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenNameSpace) { 188040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 188140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == '{') { 188240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!root_struct_def_) 188340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("no root type set to parse json with"); 188440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (builder_.GetSize()) { 188540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot have more than one json object in a file"); 188694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 188740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t toff; 188840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 188940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.Finish(Offset<Table>(toff), 189040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 189140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenEnum) { 189240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, nullptr)); 189340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenUnion) { 189440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(true, nullptr)); 189540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenRootType) { 189640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 189740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto root_type = attribute_; 189840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 189940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&root_type, nullptr)); 190040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 190140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown root type: " + root_type); 190240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (root_struct_def_->fixed) 190340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("root type must be a table"); 190440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 190540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileIdentifier) { 190640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 190740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_ = attribute_; 190840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 190940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_identifier_.length() != 191040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 191140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("file_identifier must be exactly " + 191240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 191340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " characters"); 191440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 191540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == kTokenFileExtension) { 191640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 191740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_extension_ = attribute_; 191840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 191940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 192040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenInclude) { 192140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("includes must come before declarations"); 192240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if(token_ == kTokenAttribute) { 192340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 192440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 192540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 192640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 192772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen known_attributes_[name] = false; 19281a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } else if (token_ == kTokenService) { 19291a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseService()); 193040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 193140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseDecl()); 193226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 193340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 193440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 193540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if ((*it)->predecl) { 193640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("type referenced but not defined: " + (*it)->name); 193740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 193840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 193940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 194040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &enum_def = **it; 194140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (enum_def.is_union) { 194240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto val_it = enum_def.vals.vec.begin(); 194340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val_it != enum_def.vals.vec.end(); 194440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ++val_it) { 194540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &val = **val_it; 194640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (val.struct_def && val.struct_def->fixed) 194740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only tables can be union elements: " + val.name); 194826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 194926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 195026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 195140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 195226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 195326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1954df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinezstd::set<std::string> Parser::GetIncludedFilesRecursive( 1955df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez const std::string &file_name) const { 1956df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::set<std::string> included_files; 1957df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::list<std::string> to_process; 1958df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 1959df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (file_name.empty()) return included_files; 1960df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(file_name); 1961df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 1962df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez while (!to_process.empty()) { 1963df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::string current = to_process.front(); 1964df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.pop_front(); 1965df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files.insert(current); 1966df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 1967df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez auto new_files = files_included_per_file_.at(current); 1968df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez for (auto it = new_files.begin(); it != new_files.end(); ++it) { 1969df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (included_files.find(*it) == included_files.end()) 1970df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(*it); 1971df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 1972df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 1973df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 1974df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez return included_files; 1975df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez} 1976df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 197781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Schema serialization functionality: 197881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 1979b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penketemplate<typename T> bool compareName(const T* a, const T* b) { 1980df0991b7ded0533554d3665e782273b6c8736376Xun Liu return a->defined_namespace->GetFullyQualifiedName(a->name) 1981df0991b7ded0533554d3665e782273b6c8736376Xun Liu < b->defined_namespace->GetFullyQualifiedName(b->name); 1982b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1983b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 198481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssentemplate<typename T> void AssignIndices(const std::vector<T *> &defvec) { 198581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // Pre-sort these vectors, such that we can set the correct indices for them. 198681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto vec = defvec; 1987b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(vec.begin(), vec.end(), compareName<T>); 198881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 198981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 199081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 199181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenvoid Parser::Serialize() { 199281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Clear(); 199381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(structs_.vec); 199481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(enums_.vec); 199581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Object>> object_offsets; 199681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 199772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 199881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen object_offsets.push_back(offset); 199981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 200081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 200181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Enum>> enum_offsets; 200281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 200372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 200481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enum_offsets.push_back(offset); 200581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 200681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 200781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto schema_offset = reflection::CreateSchema( 200881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_, 200981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&object_offsets), 201081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&enum_offsets), 201181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_identifier_), 201281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_extension_), 201336c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen root_struct_def_ 201436c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen ? root_struct_def_->serialized_location 201536c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen : 0); 201681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 201781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 201881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 201972fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 202072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 202181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Field>> field_offsets; 202281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2023622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen field_offsets.push_back( 2024622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen (*it)->Serialize(builder, 202572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<uint16_t>(it - fields.vec.begin()), parser)); 202681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2027df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 202881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateObject(*builder, 2029df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 203081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVectorOfSortedTables( 203181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen &field_offsets), 2032cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen fixed, 2033cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen static_cast<int>(minalign), 203472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<int>(bytesize), 203572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 203681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 203781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 203881312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 203972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen uint16_t id, 204072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 204181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateField(*builder, 204281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 204381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.type.Serialize(builder), 204481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen id, 204581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.offset, 204681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsInteger(value.type.base_type) 204781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? StringToInt(value.constant.c_str()) 204881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0, 204981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsFloat(value.type.base_type) 205081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? strtod(value.constant.c_str(), nullptr) 205181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0.0, 205281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen deprecated, 205381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen required, 205472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen key, 205572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 205681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // TODO: value.constant is almost always "0", we could save quite a bit of 205781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // space by sharing it. Same for common values of value.type. 205881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 205981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 206072fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 206172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 206281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::EnumVal>> enumval_offsets; 206381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 206481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enumval_offsets.push_back((*it)->Serialize(builder)); 206581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2066df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 206781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnum(*builder, 2068df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 206981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVector(enumval_offsets), 207081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen is_union, 207172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen underlying_type.Serialize(builder), 207272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen SerializeAttributes(builder, parser)); 207381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 207481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 207581312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const 207681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen { 207781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnumVal(*builder, 207881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 207981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value, 208081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def 208181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? struct_def->serialized_location 208281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0); 208381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 208481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 208581312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 208681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateType(*builder, 208781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(base_type), 208881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(element), 208981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def ? struct_def->index : 209081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (enum_def ? enum_def->index : -1)); 209181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 209281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 209372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssenflatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< 209472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen reflection::KeyValue>>> 209572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen Definition::SerializeAttributes(FlatBufferBuilder *builder, 209672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 209772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2098e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 2099e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen auto it = parser.known_attributes_.find(kv->first); 210072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen assert(it != parser.known_attributes_.end()); 210172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (!it->second) { // Custom attribute. 210272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen attrs.push_back( 2103e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen reflection::CreateKeyValue(*builder, builder->CreateString(kv->first), 210472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen builder->CreateString( 2105e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen kv->second->constant))); 210672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 210772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 210872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (attrs.size()) { 210972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return builder->CreateVectorOfSortedTables(&attrs); 211072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } else { 211172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return 0; 211272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 211372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen} 211472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen 211505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssenstd::string Parser::ConformTo(const Parser &base) { 211605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 211705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &struct_def = **sit; 211805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 211905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 212005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto struct_def_base = base.structs_.Lookup(qualified_name); 212105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!struct_def_base) continue; 212205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fit = struct_def.fields.vec.begin(); 212305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fit != struct_def.fields.vec.end(); ++fit) { 212405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &field = **fit; 212505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto field_base = struct_def_base->fields.Lookup(field.name); 212605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field_base) { 212705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset != field_base->value.offset) 212805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "offsets differ for field: " + field.name; 212905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.constant != field_base->value.constant) 213005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "defaults differ for field: " + field.name; 213105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 213205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "types differ for field: " + field.name; 213305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } else { 213405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // Doesn't have to exist, deleting fields is fine. 213505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // But we should check if there is a field that has the same offset 213605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // but is incompatible (in the case of field renaming). 213705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fbit = struct_def_base->fields.vec.begin(); 213805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fbit != struct_def_base->fields.vec.end(); ++fbit) { 213905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen field_base = *fbit; 214005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset == field_base->value.offset) { 214105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 214205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "field renamed to different type: " + field.name; 214305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen break; 214405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 214505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 214605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 214705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 214805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 214905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 215005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_def = **eit; 215105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 215205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 215305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_def_base = base.enums_.Lookup(qualified_name); 215405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!enum_def_base) continue; 215505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto evit = enum_def.vals.vec.begin(); 215605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen evit != enum_def.vals.vec.end(); ++evit) { 215705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_val = **evit; 215805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 215905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val_base) { 216005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val.value != enum_val_base->value) 216105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "values differ for enum: " + enum_val.name; 216205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 216305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 216405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 216505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return ""; 216605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen} 216705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen 216826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 2169