idl_parser.cpp revision 557c88c0396220e79e9a43c07f8393a5c68b739d
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> 1826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/flatbuffers.h" 2026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/idl.h" 2126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/util.h" 2226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennamespace flatbuffers { 2426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char *const kTypeNames[] = { 26557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) IDLTYPE, 2726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 2826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 2926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen nullptr 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 3126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char kTypeSizes[] = { 33557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 34557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen sizeof(CTYPE), 3526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 3626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 3726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic void Error(const std::string &msg) { 4026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen throw msg; 4126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 4226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 4426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic void CheckBitsFit(int64_t val, size_t bits) { 4526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto mask = (1ll << bits) - 1; // Bits we allow to be used. 4626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (bits < 64 && 4726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen (val & ~mask) != 0 && // Positive or unsigned. 4826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen (val | mask) != -1) // Negative. 4926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("constant does not fit in a " + NumToString(bits) + "-bit field"); 5026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 5126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 5326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentemplate<typename T> inline T atot(const char *s) { 5426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto val = StringToInt(s); 5526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen CheckBitsFit(val, sizeof(T) * 8); 5626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return (T)val; 5726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 5826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentemplate<> inline bool atot<bool>(const char *s) { 5926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return 0 != atoi(s); 6026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 6126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentemplate<> inline float atot<float>(const char *s) { 6226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return static_cast<float>(strtod(s, nullptr)); 6326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 6426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentemplate<> inline double atot<double>(const char *s) { 6526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return strtod(s, nullptr); 6626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 6726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssentemplate<> inline Offset<void> atot<Offset<void>>(const char *s) { 6926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return Offset<void>(atoi(s)); 7026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 7126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 7226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 7326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 7426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 7526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 7626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 7726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 7826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 7926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Identifier, 260, "identifier") \ 8026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Table, 261, "table") \ 8126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Struct, 262, "struct") \ 8226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Enum, 263, "enum") \ 8326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Union, 264, "union") \ 8426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(NameSpace, 265, "namespace") \ 855da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(RootType, 266, "root_type") \ 865da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen TD(FileIdentifier, 267, "file_identifier") \ 87be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen TD(FileExtension, 268, "file_extension") \ 88be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen TD(Include, 269, "include") 898f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 908f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 918f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 9226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 9375349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 9426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 9526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 96557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 97557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen kToken ## ENUM, 9826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 9926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 10026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 10126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 10326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 10426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 10526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 10626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 107557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) IDLTYPE, 10826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 10926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 11026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 11126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 11226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 1138e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 11426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 11526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 11626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 11726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 11826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 120ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 121ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssenint64_t Parser::ParseHexNum(int nibbles) { 122ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 123ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen if (!isxdigit(cursor_[i])) 124ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen Error("escape code must be followed by " + NumToString(nibbles) + 125ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen " hex digits"); 126ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen auto val = StringToInt(cursor_, 16); 127ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 128ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen return val; 129ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 130ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 13126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::Next() { 13226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 13326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 13426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 13526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 13626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 13726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 13826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return; 13926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 14026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 14126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': return; 14226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ',': case ':': case ';': case '=': return; 14326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 14426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if(!isdigit(*cursor_)) return; 14526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("floating point constant can\'t start with \".\""); 14626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 14726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 14826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ = ""; 14926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (*cursor_ != '\"') { 15026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 15126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("illegal character in string constant"); 15226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 15326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 15426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 15526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 15626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 15726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 158ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 159ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 16026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 16126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 162ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 163ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 164ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 165ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen attribute_ += static_cast<char>(ParseHexNum(2)); 166ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 167ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 168ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 169ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 170ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen ToUTF8(static_cast<int>(ParseHexNum(4)), &attribute_); 171ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 172ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: Error("unknown escape code in string constant"); break; 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 17526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 17626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 17726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 17826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 17926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 18026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 18126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; 18226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 18326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 18426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 18526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (*cursor_ && *cursor_ != '\n') cursor_++; 18626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 18726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!seen_newline) 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("a documentation comment should be on a line on its own"); 18926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // todo: do we want to support multiline comments instead? 19026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_ += std::string(start + 1, cursor_); 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 19226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 19526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 19626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (isalpha(static_cast<unsigned char>(c))) { 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 19826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.clear(); 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 20426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // First, see if it is a type keyword from the table of types: 205557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 20626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == IDLTYPE) { \ 20726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kToken ## ENUM; \ 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; \ 20926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 21026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 21126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 21226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If it's a boolean constant keyword, turn those into integers, 21326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // which simplifies our logic downstream. 21426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "true" || attribute_ == "false") { 21526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ = NumToString(attribute_ == "true"); 21626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 21726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; 21826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 21926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Check for declaration keywords: 22026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "table") { token_ = kTokenTable; return; } 22126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "struct") { token_ = kTokenStruct; return; } 22226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "enum") { token_ = kTokenEnum; return; } 22326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "union") { token_ = kTokenUnion; return; } 22426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "namespace") { token_ = kTokenNameSpace; return; } 22526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (attribute_ == "root_type") { token_ = kTokenRootType; return; } 226be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen if (attribute_ == "include") { token_ = kTokenInclude; return; } 2275da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_identifier") { 2285da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileIdentifier; 2295da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen return; 2305da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 2315da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (attribute_ == "file_extension") { 2325da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen token_ = kTokenFileExtension; 2335da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen return; 2345da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } 23526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // If not, it is a user-defined identifier: 23626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 23726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; 23826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 23926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 24026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 24126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '.') { 24226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 24326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 24493df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 24593df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 24693df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 24793df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 24893df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 24993df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 25093df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 25226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 25326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 25426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 25526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.clear(); 25626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 25726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; 25826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 25926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 26026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 26126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 26226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("illegal character: " + ch); 26326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 26426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 26526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 26626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 26726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 26826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Check if a given token is next, if so, consume it as well. 26926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::IsNext(int t) { 27026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool isnext = t == token_; 27126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (isnext) Next(); 27226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return isnext; 27326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 27426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 27526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 27626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::Expect(int t) { 27726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 27826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("expecting: " + TokenToString(t) + " instead got: " + 27926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TokenToString(token_)); 28026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 28126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 28226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 28326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 28426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 28526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseType(Type &type) { 28626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) { 28726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.base_type = static_cast<BaseType>(token_ - kTokenNONE); 28826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 28926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == kTokenIdentifier) { 29026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto enum_def = enums_.Lookup(attribute_); 29126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (enum_def) { 29226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type = enum_def->underlying_type; 29326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 29426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 29526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 29626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.struct_def = LookupCreateStruct(attribute_); 29726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 29826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == '[') { 29926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 30026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type subtype; 30126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseType(subtype); 30226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 30326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this, but it will complicate things, and it's 30426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // easier to work around with a struct around the inner vector. 30526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("nested vector types not supported (wrap in table first)."); 30626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 30726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (subtype.base_type == BASE_TYPE_UNION) { 30826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // We could support this if we stored a struct of 2 elements per 30926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // union element. 31026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("vector of union types not supported (wrap in table first)."); 31126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3123fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 31326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen type.element = subtype.base_type; 31426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(']'); 31526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return; 31626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 31726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("illegal type syntax"); 31826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 31926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 32126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 32226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 32326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenFieldDef &Parser::AddField(StructDef &struct_def, 32426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const std::string &name, 32526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const Type &type) { 32626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 32726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 32826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 32926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 33026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 33126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 33226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 33326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 33426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 33526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 33626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 33726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 3381256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 33926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 34026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 34126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 34226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("field already exists: " + name); 34326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return field; 34426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 34526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 34626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseField(StructDef &struct_def) { 34726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 34826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string dc = doc_comment_; 34926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 35026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(':'); 35126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 35226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseType(type); 35326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 35426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 35526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("structs_ may contain only scalar or struct fields"); 35626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3579140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 35826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 35926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 36026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // with _type appended as the name. 3619140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield = &AddField(struct_def, name + "_type", 3629140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen type.enum_def->underlying_type); 36326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 36426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 36526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = AddField(struct_def, name, type); 36626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 36726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 36826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 36915dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 37015dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen Error("default values currently only supported for scalars"); 37126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseSingleValue(field.value); 37226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 37326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 37426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.doc_comment = dc; 37526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseMetaData(field); 37626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.deprecated = field.attributes.Lookup("deprecated") != nullptr; 37726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (field.deprecated && struct_def.fixed) 37826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("can't deprecate fields in a struct"); 3793e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen auto nested = field.attributes.Lookup("nested_flatbuffer"); 3803e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 3813e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 3823e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen Error("nested_flatbuffer attribute must be a string (the root type)"); 3833e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (field.value.type.base_type != BASE_TYPE_VECTOR || 3843e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen field.value.type.element != BASE_TYPE_UCHAR) 3853e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen Error("nested_flatbuffer attribute may only apply to a vector of ubyte"); 3863e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 3873e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 3883e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 3893e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 39026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3919140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 3929140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 3939140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 3949140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto attr = field.attributes.Lookup("id"); 3959140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 3969140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 3979140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 3989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 3999140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 4009140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 4019140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 4029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 4039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 40426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(';'); 40526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 40626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 40726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseAnyValue(Value &val, FieldDef *field) { 40826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 40926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 41026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 41126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!field_stack_.size() || 41226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.back().second->value.type.base_type != BASE_TYPE_UTYPE) 41326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("missing type field before this union value: " + field->name); 41426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto enum_idx = atot<unsigned char>( 41526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.back().first.constant.c_str()); 4163fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 4173fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen if (!enum_val) Error("illegal type id for: " + field->name); 4183fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen val.constant = NumToString(ParseTable(*enum_val->struct_def)); 41926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 42026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 42126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 42226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.constant = NumToString(ParseTable(*val.type.struct_def)); 42326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 42426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 42526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto s = attribute_; 42626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenStringConstant); 42726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 42826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 42926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 43026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 43126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect('['); 43226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.constant = NumToString(ParseVector(val.type.VectorType())); 43326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 43426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 43526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 43626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseSingleValue(val); 43726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 43826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 43926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 44026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 44126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 44226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto off = atot<uoffset_t>(val.constant.c_str()); 44326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(struct_stack_.size() - off == struct_def.bytesize); 44426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 44526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PushBytes(&struct_stack_[off], struct_def.bytesize); 44626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_stack_.resize(struct_stack_.size() - struct_def.bytesize); 44726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 44826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 44926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 45026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenuoffset_t Parser::ParseTable(const StructDef &struct_def) { 45126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect('{'); 45226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size_t fieldn = 0; 4530b47e69d4d6cb6905388f28760a6a90e96380a82Wouter van Oortmerssen if (!IsNext('}')) for (;;) { 45426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 45526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!IsNext(kTokenStringConstant)) Expect(kTokenIdentifier); 45626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = struct_def.fields.Lookup(name); 45726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!field) Error("unknown field: " + name); 45826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && (fieldn >= struct_def.fields.vec.size() 45926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen || struct_def.fields.vec[fieldn] != field)) { 46026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("struct field appearing out of order: " + name); 46126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 46226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(':'); 46326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val = field->value; 46426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseAnyValue(val, field); 46526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.push_back(std::make_pair(val, field)); 46626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen fieldn++; 46726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsNext('}')) break; 46826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(','); 46926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 47011f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen for (auto it = field_stack_.rbegin(); 47111f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 47211f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen if (it->second->used) 47311f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen Error("field set more than once: " + it->second->name); 47411f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen it->second->used = true; 47511f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen } 47611f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen for (auto it = field_stack_.rbegin(); 47711f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 47811f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen it->second->used = false; 47911f25386100ce50e114ec52d5487027af2912ebfWouter van Oortmerssen } 48026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && fieldn != struct_def.fields.vec.size()) 48126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("incomplete struct initialization: " + struct_def.name); 48226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 48326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 48426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 48526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 48626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 48726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 48826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 48926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 49026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = field_stack_.rbegin(); 49126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen it != field_stack_.rbegin() + fieldn; ++it) { 49226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &value = it->first; 49326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 49426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!struct_def.sortbysize || size == SizeOf(value.type.base_type)) { 49526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (value.type.base_type) { 496557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 49726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 49826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 499be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 500be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.PushElement(atot<CTYPE>(value.constant.c_str())); \ 501be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 502be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.AddElement(value.offset, \ 50326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen atot<CTYPE>( value.constant.c_str()), \ 50426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen atot<CTYPE>(field->value.constant.c_str())); \ 505be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 50626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 50726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 50826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 509557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 51026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 51126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 51226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 51326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen SerializeStruct(*field->value.type.struct_def, value); \ 51426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 51526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddOffset(value.offset, \ 51626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen atot<CTYPE>(value.constant.c_str())); \ 51726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 51826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 51926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 52026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 52126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 52226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 52326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 52426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 52526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t i = 0; i < fieldn; i++) field_stack_.pop_back(); 52626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 52726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 52826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 52926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 53026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Temporarily store this struct in a side buffer, since this data has to 53126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // be stored in-line later in the parent object. 53226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto off = struct_stack_.size(); 53326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_stack_.insert(struct_stack_.end(), 53426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.GetBufferPointer(), 53526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.GetBufferPointer() + struct_def.bytesize); 53626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 53726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return static_cast<uoffset_t>(off); 53826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 53926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return builder_.EndTable( 54026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen start, 54126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static_cast<voffset_t>(struct_def.fields.vec.size())); 54226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 54326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 54426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 54526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenuoffset_t Parser::ParseVector(const Type &type) { 54626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen int count = 0; 54726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ != ']') for (;;) { 54826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 54926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen val.type = type; 55026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseAnyValue(val, NULL); 55126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.push_back(std::make_pair(val, nullptr)); 55226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen count++; 55326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == ']') break; 55426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(','); 55526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 55626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 55726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 558be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 559be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 56026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (int i = 0; i < count; i++) { 56126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 56226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 56326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 564557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \ 56526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 56626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 56726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen else builder_.PushElement(atot<CTYPE>(val.constant.c_str())); \ 56826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 56926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 57026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 57126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 57326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 57426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 57526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 57626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return builder_.EndVector(count); 57726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 57826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 57926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseMetaData(Definition &def) { 58026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsNext('(')) { 58126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 58226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 58326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 58426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 58526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen def.attributes.Add(name, e); 58626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsNext(':')) { 58726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseSingleValue(*e); 58826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 58926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsNext(')')) break; 59026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(','); 59126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 59226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 59326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 59426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 59526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::TryTypedValue(int dtoken, 59626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool check, 59726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value &e, 59826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen BaseType req) { 59926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 60026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 60126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 60226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 60326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 60426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 60526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 60626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error(std::string("type mismatch: expecting: ") + 60726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen kTypeNames[e.type.base_type] + 60826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ", found: " + 60926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen kTypeNames[req]); 61026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 61126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 61226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 61326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 61426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return match; 61526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 61626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6179c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssenint64_t Parser::ParseIntegerFromString(Type &type) { 6189c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen int64_t result = 0; 6199c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 6209c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 6219c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 6229c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 6239c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 6249c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 6259c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 6269c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 6279c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 6289c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 6299c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 6309c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 6319c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 6329c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 6339c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 6349c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen Error("unknown enum value: " + word + 6359c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 6369c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen result |= enum_val->value; 6379c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 6389c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 6399c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen Error("not a valid value for this field: " + word); 6409c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 6419c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *dot = strchr(word.c_str(), '.'); 6429c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!dot) Error("enum values need to be qualified by an enum type"); 6439c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 6449c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 6459c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_def = enums_.Lookup(enum_def_str); 6469c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_def) Error("unknown enum: " + enum_def_str); 6479c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 6489c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) Error("unknown enum value: " + enum_val_str); 6499c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen result |= enum_val->value; 6509c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 6519c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 6529c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen return result; 6539c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 6549c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 65526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseSingleValue(Value &e) { 6569c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // First check if this could be a string/identifier enum value: 6579c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (e.type.base_type != BASE_TYPE_STRING && 6589c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 6599c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 6609c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.constant = NumToString(ParseIntegerFromString(e.type)); 6619c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen Next(); 6623fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen } else if (TryTypedValue(kTokenIntegerConstant, 66326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen IsScalar(e.type.base_type), 66426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e, 66526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen BASE_TYPE_INT) || 66626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TryTypedValue(kTokenFloatConstant, 66726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen IsFloat(e.type.base_type), 66826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e, 66926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen BASE_TYPE_FLOAT) || 67026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TryTypedValue(kTokenStringConstant, 67126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 67226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e, 67326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen BASE_TYPE_STRING)) { 67426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 67526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("cannot parse value starting with: " + TokenToString(token_)); 67626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 67726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 67826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 67926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name) { 68026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto struct_def = structs_.Lookup(name); 68126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!struct_def) { 68226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 68326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 68426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 68526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen structs_.Add(name, struct_def); 68626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def->name = name; 68726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def->predecl = true; 688c2ba7fd251b9da9fd2f0210818cc0221682f29c4Wouter van Oortmerssen struct_def->defined_namespace = namespaces_.back(); 68926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 69026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 69126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 69226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 69326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseEnum(bool is_union) { 69426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string dc = doc_comment_; 69526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 69626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 69726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 69826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 69926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.name = name; 70026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.doc_comment = dc; 70126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 70226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (enums_.Add(name, &enum_def)) Error("enum already exists: " + name); 70326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 70426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 70526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 706a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 707a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen // Give specialized error message, since this type spec used to 708a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen // be optional in the first FlatBuffers release. 709a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen if (!IsNext(':')) Error("must specify the underlying integer type for this" 710a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 711a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen // Specify the integer type underlying this enum. 71226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseType(enum_def.underlying_type); 71326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 71426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("underlying enum type must be integral"); 7153fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 7163fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 71726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 71826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseMetaData(enum_def); 71926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect('{'); 72026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 72126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen do { 72226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 72326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string dc = doc_comment_; 72426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 72526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 726127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen auto value = enum_def.vals.vec.size() 727127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 728127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen : 0; 729127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen auto &ev = *new EnumVal(name, value); 73026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (enum_def.vals.Add(name, &ev)) 73126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("enum value already exists: " + name); 73226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ev.doc_comment = dc; 73326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 73426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ev.struct_def = LookupCreateStruct(name); 73526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 73626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsNext('=')) { 73726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ev.value = atoi(attribute_.c_str()); 73826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIntegerConstant); 73926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (prevsize && enum_def.vals.vec[prevsize - 1]->value >= ev.value) 74026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("enum values must be specified in ascending order"); 74126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 742c553b6b950870b299b40e0153818430c649b76cfWouter van Oortmerssen } while (IsNext(',') && token_ != '}'); 74326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect('}'); 744127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 745127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 746127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 747127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 748127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 749127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen Error("bit flag out of range of underlying integral type"); 7509c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 751127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 752127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 75326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 75426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 75526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::ParseDecl() { 75626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string dc = doc_comment_; 75726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool fixed = IsNext(kTokenStruct); 75826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!fixed) Expect(kTokenTable); 75926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 76026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 76126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name); 76226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!struct_def.predecl) Error("datatype already exists: " + name); 76326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 76426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 76526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.doc_comment = dc; 76626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.fixed = fixed; 76726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 76826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // to preserve declartion order. 76926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen remove(structs_.vec.begin(), structs_.vec.end(), &struct_def); 77026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen structs_.vec.back() = &struct_def; 77126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseMetaData(struct_def); 77226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.sortbysize = 77326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.attributes.Lookup("original_order") == nullptr && !fixed; 77426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect('{'); 77526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (token_ != '}') ParseField(struct_def); 77626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto force_align = struct_def.attributes.Lookup("force_align"); 77726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 77826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 77926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 78026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align < struct_def.minalign || 78126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align > 256 || 78226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 78326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("force_align must be a power of two integer ranging from the" 78426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen "struct\'s natural alignment to 256"); 78526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = align; 78626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 78765cfa18855abc712faa1bf0cb5c3b88ab8df4b28Wouter van Oortmerssen struct_def.PadLastField(struct_def.minalign); 7889140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 7899140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto &fields = struct_def.fields.vec; 7909140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (!struct_def.fixed && fields.size()) { 7917fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 7929140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 7939140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 7949140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7959140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 7969140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 7979140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 7989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 7999140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen Error("either all fields or no fields must have an 'id' attribute"); 8009140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 8019140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 8029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen std::sort(fields.begin(), fields.end(), 8039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen [](const FieldDef *a, const FieldDef *b) -> bool { 8049140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 8059140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 8069140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen return a_id < b_id; 8079140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen }); 8089140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 8099140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 8109140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 8119140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen Error("field id\'s must be consecutive from 0, id " + 8129140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 8139140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 8149140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 8159140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 8169140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 817541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen // Check that no identifiers clash with auto generated fields. 818541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen // This is not an ideal situation, but should occur very infrequently, 819541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen // and allows us to keep using very readable names for type & length fields 820541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen // without inducing compile errors. 821541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen auto CheckClash = [&fields, &struct_def](const char *suffix, 822541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen BaseType basetype) { 823541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen auto len = strlen(suffix); 824541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 825541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen auto &name = (*it)->name; 826541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen if (name.length() > len && 827541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen name.compare(name.length() - len, len, suffix) == 0 && 828541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 829541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen auto field = struct_def.fields.Lookup( 830541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen name.substr(0, name.length() - len)); 831541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen if (field && field->value.type.base_type == basetype) 832541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen Error("Field " + name + 833541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen " would clash with generated functions for field " + 834541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen field->name); 835541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen } 836541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen } 837541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen }; 838541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen CheckClash("_type", BASE_TYPE_UNION); 839541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen CheckClash("Type", BASE_TYPE_UNION); 840541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen CheckClash("_length", BASE_TYPE_VECTOR); 841541b06759f72dcff9008478da797957e6fbabb45Wouter van Oortmerssen CheckClash("Length", BASE_TYPE_VECTOR); 84265cfa18855abc712faa1bf0cb5c3b88ab8df4b28Wouter van Oortmerssen Expect('}'); 84326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 84426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 84526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 84626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen root_struct_def = structs_.Lookup(name); 84726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return root_struct_def != nullptr; 84826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 84926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 850be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 851be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // Since the Parser object retains definitions across files, we must 852be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // ensure we only output code for definitions once, in the file they are first 853be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // declared. This function marks all existing definitions as having already 854be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // been generated. 855be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 856be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 857be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 858be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 859be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 860be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 861be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 862be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 863be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 864be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 865e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths) { 86626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen source_ = cursor_ = source; 86726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen line_ = 1; 86826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen error_.clear(); 86926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 87026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen try { 87126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 872be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // Includes must come first: 873be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen while (IsNext(kTokenInclude)) { 874be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen auto name = attribute_; 875be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen Expect(kTokenStringConstant); 876be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen if (included_files_.find(name) == included_files_.end()) { 877be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // We found an include file that we have not parsed yet. 878be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // Load it and parse it. 879be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen std::string contents; 880e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen if (!include_paths) { 881e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen const char *current_directory[] = { "", nullptr }; 882e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen include_paths = current_directory; 883e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen } 884e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 885e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen auto filepath = flatbuffers::ConCatPathFileName(*paths, name); 886e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen if(LoadFile(filepath.c_str(), true, &contents)) break; 887e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen } 888e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen if (contents.empty()) 889be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen Error("unable to load include file: " + name); 890e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen included_files_[name] = true; 891e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen if (!Parse(contents.c_str(), include_paths)) { 892e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen // Any errors, we're done. 893e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen return false; 894e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen } 895be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // We do not want to output code for any included files: 896be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen MarkGenerated(); 897be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // This is the easiest way to continue this file after an include: 898be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 899be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // file anew. This will cause it to encounter the same include statement 900be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // again, but this time it will skip it, because it was entered into 901be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // included_files_. 902e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen // This is recursive, but only go as deep as the number of include 903e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen // statements. 904e57b86bb9f17cabc5bf5b4afe78153dde55f46eaWouter van Oortmerssen return Parse(source, include_paths); 905be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 906be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen Expect(';'); 907be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 908be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen // Now parse all other kinds of declarations: 90926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (token_ != kTokenEof) { 91026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == kTokenNameSpace) { 91126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 912c2ba7fd251b9da9fd2f0210818cc0221682f29c4Wouter van Oortmerssen auto ns = new Namespace(); 913c2ba7fd251b9da9fd2f0210818cc0221682f29c4Wouter van Oortmerssen namespaces_.push_back(ns); 91426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 915c2ba7fd251b9da9fd2f0210818cc0221682f29c4Wouter van Oortmerssen ns->components.push_back(attribute_); 91626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 91726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!IsNext('.')) break; 91826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 91926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(';'); 92026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == '{') { 92126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!root_struct_def) Error("no root type set to parse json with"); 92226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (builder_.GetSize()) { 92326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("cannot have more than one json object in a file"); 92426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 92509a2999c66abc92e5c33fdef75c63dec81f90a3aWouter van Oortmerssen builder_.Finish(Offset<Table>(ParseTable(*root_struct_def)), 92609a2999c66abc92e5c33fdef75c63dec81f90a3aWouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 92726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == kTokenEnum) { 92826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseEnum(false); 92926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == kTokenUnion) { 93026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseEnum(true); 93126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (token_ == kTokenRootType) { 93226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Next(); 93326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto root_type = attribute_; 93426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Expect(kTokenIdentifier); 93526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 93626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("unknown root type: " + root_type); 93726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (root_struct_def->fixed) 93826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("root type must be a table"); 9395da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Expect(';'); 9405da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } else if (token_ == kTokenFileIdentifier) { 9415da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Next(); 9425da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen file_identifier_ = attribute_; 9435da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Expect(kTokenStringConstant); 9445da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen if (file_identifier_.length() != 9455da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 9465da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Error("file_identifier must be exactly " + 9475da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 9485da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen " characters"); 9495da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Expect(';'); 9505da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen } else if (token_ == kTokenFileExtension) { 9515da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Next(); 9525da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen file_extension_ = attribute_; 9535da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Expect(kTokenStringConstant); 9545da7bda826a98fa92eb1356907afa631bfa9c1b1Wouter van Oortmerssen Expect(';'); 955be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } else if(token_ == kTokenInclude) { 956be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen Error("includes must come before declarations"); 95726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 95826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ParseDecl(); 95926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 96226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if ((*it)->predecl) 96326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("type referenced but not defined: " + (*it)->name); 96426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 96626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = **it; 96726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (enum_def.is_union) { 96826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); 96926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen it != enum_def.vals.vec.end(); 97026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ++it) { 97126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = **it; 97226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (val.struct_def && val.struct_def->fixed) 97326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Error("only tables can be union elements: " + val.name); 97426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 97526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 97626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 97726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } catch (const std::string &msg) { 97826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen error_ = "line " + NumToString(line_) + ": " + msg; 97926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return false; 98026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 98126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(!struct_stack_.size()); 98226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return true; 98326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 98426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 98526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 986