mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 12:05:50 +00:00
Added namespaced way to refer to types in schemas.
Also made proper namespacing work for enums. You can now say namespace.MyTable as the type when declaring a field that refers to a type in a different namespace. Previously, it would work just referring to MyTable, however with the recent commit fixing namespaced types this now is ambiguous. Change-Id: Ieaa3f4ac1662b8c4dc1f16e1898ea3cdb02e10fd Tested: on Linux.
This commit is contained in:
@@ -285,14 +285,33 @@ void Parser::Expect(int t) {
|
||||
Next();
|
||||
}
|
||||
|
||||
void Parser::ParseNamespacing(std::string *id, std::string *last) {
|
||||
while (IsNext('.')) {
|
||||
*id += ".";
|
||||
*id += attribute_;
|
||||
if (last) *last = attribute_;
|
||||
Expect(kTokenIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
EnumDef *Parser::LookupEnum(const std::string &id) {
|
||||
auto ed = enums_.Lookup(GetFullyQualifiedName(id));
|
||||
// id may simply not have a namespace at all, so check that too.
|
||||
if (!ed) ed = enums_.Lookup(id);
|
||||
return ed;
|
||||
}
|
||||
|
||||
void Parser::ParseTypeIdent(Type &type) {
|
||||
auto enum_def = enums_.Lookup(attribute_);
|
||||
std::string id = attribute_;
|
||||
Expect(kTokenIdentifier);
|
||||
ParseNamespacing(&id, nullptr);
|
||||
auto enum_def = LookupEnum(id);
|
||||
if (enum_def) {
|
||||
type = enum_def->underlying_type;
|
||||
if (enum_def->is_union) type.base_type = BASE_TYPE_UNION;
|
||||
} else {
|
||||
type.base_type = BASE_TYPE_STRUCT;
|
||||
type.struct_def = LookupCreateStruct(attribute_);
|
||||
type.struct_def = LookupCreateStruct(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +319,7 @@ void Parser::ParseTypeIdent(Type &type) {
|
||||
void Parser::ParseType(Type &type) {
|
||||
if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) {
|
||||
type.base_type = static_cast<BaseType>(token_ - kTokenNONE);
|
||||
Next();
|
||||
} else {
|
||||
if (token_ == kTokenIdentifier) {
|
||||
ParseTypeIdent(type);
|
||||
@@ -320,12 +340,10 @@ void Parser::ParseType(Type &type) {
|
||||
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
|
||||
type.element = subtype.base_type;
|
||||
Expect(']');
|
||||
return;
|
||||
} else {
|
||||
Error("illegal type syntax");
|
||||
}
|
||||
}
|
||||
Next();
|
||||
}
|
||||
|
||||
FieldDef &Parser::AddField(StructDef &struct_def,
|
||||
@@ -709,11 +727,11 @@ int64_t Parser::ParseIntegerFromString(Type &type) {
|
||||
if (!IsInteger(type.base_type))
|
||||
Error("not a valid value for this field: " + word);
|
||||
// TODO: could check if its a valid number constant here.
|
||||
const char *dot = strchr(word.c_str(), '.');
|
||||
const char *dot = strrchr(word.c_str(), '.');
|
||||
if (!dot) Error("enum values need to be qualified by an enum type");
|
||||
std::string enum_def_str(word.c_str(), dot);
|
||||
std::string enum_val_str(dot + 1, word.c_str() + word.length());
|
||||
auto enum_def = enums_.Lookup(enum_def_str);
|
||||
auto enum_def = LookupEnum(enum_def_str);
|
||||
if (!enum_def) Error("unknown enum: " + enum_def_str);
|
||||
auto enum_val = enum_def->vals.Lookup(enum_val_str);
|
||||
if (!enum_val) Error("unknown enum value: " + enum_val_str);
|
||||
@@ -775,6 +793,8 @@ void Parser::ParseSingleValue(Value &e) {
|
||||
StructDef *Parser::LookupCreateStruct(const std::string &name) {
|
||||
std::string qualified_name = GetFullyQualifiedName(name);
|
||||
auto struct_def = structs_.Lookup(qualified_name);
|
||||
// Unqualified names may simply have no namespace at all, so try that too.
|
||||
if (!struct_def) struct_def = structs_.Lookup(name);
|
||||
if (!struct_def) {
|
||||
// Rather than failing, we create a "pre declared" StructDef, due to
|
||||
// circular references, and check for errors at the end of parsing.
|
||||
@@ -798,7 +818,8 @@ void Parser::ParseEnum(bool is_union) {
|
||||
enum_def.doc_comment = enum_comment;
|
||||
enum_def.is_union = is_union;
|
||||
enum_def.defined_namespace = namespaces_.back();
|
||||
if (enums_.Add(enum_name, &enum_def)) Error("enum already exists: " + enum_name);
|
||||
if (enums_.Add(GetFullyQualifiedName(enum_name), &enum_def))
|
||||
Error("enum already exists: " + enum_name);
|
||||
if (is_union) {
|
||||
enum_def.underlying_type.base_type = BASE_TYPE_UTYPE;
|
||||
enum_def.underlying_type.enum_def = &enum_def;
|
||||
@@ -822,9 +843,11 @@ void Parser::ParseEnum(bool is_union) {
|
||||
Expect('{');
|
||||
if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0));
|
||||
do {
|
||||
std::string value_name = attribute_;
|
||||
auto value_name = attribute_;
|
||||
auto full_name = value_name;
|
||||
std::vector<std::string> value_comment = doc_comment_;
|
||||
Expect(kTokenIdentifier);
|
||||
if (is_union) ParseNamespacing(&full_name, &value_name);
|
||||
auto prevsize = enum_def.vals.vec.size();
|
||||
auto value = enum_def.vals.vec.size()
|
||||
? enum_def.vals.vec.back()->value + 1
|
||||
@@ -834,7 +857,7 @@ void Parser::ParseEnum(bool is_union) {
|
||||
Error("enum value already exists: " + value_name);
|
||||
ev.doc_comment = value_comment;
|
||||
if (is_union) {
|
||||
ev.struct_def = LookupCreateStruct(value_name);
|
||||
ev.struct_def = LookupCreateStruct(full_name);
|
||||
}
|
||||
if (IsNext('=')) {
|
||||
ev.value = atoi(attribute_.c_str());
|
||||
@@ -1104,7 +1127,6 @@ Type Parser::ParseTypeFromProtoType() {
|
||||
}
|
||||
}
|
||||
ParseTypeIdent(type);
|
||||
Expect(kTokenIdentifier);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user