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.
parent ecb27817
...@@ -329,6 +329,8 @@ class Parser { ...@@ -329,6 +329,8 @@ class Parser {
void Next(); void Next();
bool IsNext(int t); bool IsNext(int t);
void Expect(int t); void Expect(int t);
EnumDef *LookupEnum(const std::string &id);
void ParseNamespacing(std::string *id, std::string *last);
void ParseTypeIdent(Type &type); void ParseTypeIdent(Type &type);
void ParseType(Type &type); void ParseType(Type &type);
FieldDef &AddField(StructDef &struct_def, FieldDef &AddField(StructDef &struct_def,
......
...@@ -285,14 +285,33 @@ void Parser::Expect(int t) { ...@@ -285,14 +285,33 @@ void Parser::Expect(int t) {
Next(); 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) { 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) { if (enum_def) {
type = enum_def->underlying_type; type = enum_def->underlying_type;
if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; if (enum_def->is_union) type.base_type = BASE_TYPE_UNION;
} else { } else {
type.base_type = BASE_TYPE_STRUCT; 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) { ...@@ -300,6 +319,7 @@ void Parser::ParseTypeIdent(Type &type) {
void Parser::ParseType(Type &type) { void Parser::ParseType(Type &type) {
if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) { if (token_ >= kTokenBOOL && token_ <= kTokenSTRING) {
type.base_type = static_cast<BaseType>(token_ - kTokenNONE); type.base_type = static_cast<BaseType>(token_ - kTokenNONE);
Next();
} else { } else {
if (token_ == kTokenIdentifier) { if (token_ == kTokenIdentifier) {
ParseTypeIdent(type); ParseTypeIdent(type);
...@@ -320,12 +340,10 @@ void Parser::ParseType(Type &type) { ...@@ -320,12 +340,10 @@ void Parser::ParseType(Type &type) {
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
type.element = subtype.base_type; type.element = subtype.base_type;
Expect(']'); Expect(']');
return;
} else { } else {
Error("illegal type syntax"); Error("illegal type syntax");
} }
} }
Next();
} }
FieldDef &Parser::AddField(StructDef &struct_def, FieldDef &Parser::AddField(StructDef &struct_def,
...@@ -709,11 +727,11 @@ int64_t Parser::ParseIntegerFromString(Type &type) { ...@@ -709,11 +727,11 @@ int64_t Parser::ParseIntegerFromString(Type &type) {
if (!IsInteger(type.base_type)) if (!IsInteger(type.base_type))
Error("not a valid value for this field: " + word); Error("not a valid value for this field: " + word);
// TODO: could check if its a valid number constant here. // 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"); 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_def_str(word.c_str(), dot);
std::string enum_val_str(dot + 1, word.c_str() + word.length()); 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); if (!enum_def) Error("unknown enum: " + enum_def_str);
auto enum_val = enum_def->vals.Lookup(enum_val_str); auto enum_val = enum_def->vals.Lookup(enum_val_str);
if (!enum_val) Error("unknown enum value: " + enum_val_str); if (!enum_val) Error("unknown enum value: " + enum_val_str);
...@@ -775,6 +793,8 @@ void Parser::ParseSingleValue(Value &e) { ...@@ -775,6 +793,8 @@ void Parser::ParseSingleValue(Value &e) {
StructDef *Parser::LookupCreateStruct(const std::string &name) { StructDef *Parser::LookupCreateStruct(const std::string &name) {
std::string qualified_name = GetFullyQualifiedName(name); std::string qualified_name = GetFullyQualifiedName(name);
auto struct_def = structs_.Lookup(qualified_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) { if (!struct_def) {
// Rather than failing, we create a "pre declared" StructDef, due to // Rather than failing, we create a "pre declared" StructDef, due to
// circular references, and check for errors at the end of parsing. // circular references, and check for errors at the end of parsing.
...@@ -798,7 +818,8 @@ void Parser::ParseEnum(bool is_union) { ...@@ -798,7 +818,8 @@ void Parser::ParseEnum(bool is_union) {
enum_def.doc_comment = enum_comment; enum_def.doc_comment = enum_comment;
enum_def.is_union = is_union; enum_def.is_union = is_union;
enum_def.defined_namespace = namespaces_.back(); 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) { if (is_union) {
enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; enum_def.underlying_type.base_type = BASE_TYPE_UTYPE;
enum_def.underlying_type.enum_def = &enum_def; enum_def.underlying_type.enum_def = &enum_def;
...@@ -822,9 +843,11 @@ void Parser::ParseEnum(bool is_union) { ...@@ -822,9 +843,11 @@ void Parser::ParseEnum(bool is_union) {
Expect('{'); Expect('{');
if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0));
do { do {
std::string value_name = attribute_; auto value_name = attribute_;
auto full_name = value_name;
std::vector<std::string> value_comment = doc_comment_; std::vector<std::string> value_comment = doc_comment_;
Expect(kTokenIdentifier); Expect(kTokenIdentifier);
if (is_union) ParseNamespacing(&full_name, &value_name);
auto prevsize = enum_def.vals.vec.size(); auto prevsize = enum_def.vals.vec.size();
auto value = enum_def.vals.vec.size() auto value = enum_def.vals.vec.size()
? enum_def.vals.vec.back()->value + 1 ? enum_def.vals.vec.back()->value + 1
...@@ -834,7 +857,7 @@ void Parser::ParseEnum(bool is_union) { ...@@ -834,7 +857,7 @@ void Parser::ParseEnum(bool is_union) {
Error("enum value already exists: " + value_name); Error("enum value already exists: " + value_name);
ev.doc_comment = value_comment; ev.doc_comment = value_comment;
if (is_union) { if (is_union) {
ev.struct_def = LookupCreateStruct(value_name); ev.struct_def = LookupCreateStruct(full_name);
} }
if (IsNext('=')) { if (IsNext('=')) {
ev.value = atoi(attribute_.c_str()); ev.value = atoi(attribute_.c_str());
...@@ -1104,7 +1127,6 @@ Type Parser::ParseTypeFromProtoType() { ...@@ -1104,7 +1127,6 @@ Type Parser::ParseTypeFromProtoType() {
} }
} }
ParseTypeIdent(type); ParseTypeIdent(type);
Expect(kTokenIdentifier);
return type; return type;
} }
......
...@@ -39,7 +39,7 @@ table Monster { ...@@ -39,7 +39,7 @@ table Monster {
/// multiline too /// multiline too
testarrayoftables:[Monster] (id: 11); testarrayoftables:[Monster] (id: 11);
testarrayofstring:[string] (id: 10); testarrayofstring:[string] (id: 10);
enemy:Monster (id:12); enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace.
test:Any (id: 8); test:Any (id: 8);
test4:[Test] (id: 9); test4:[Test] (id: 9);
testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster"); testnestedflatbuffer:[ubyte] (id:13, nested_flatbuffer: "Monster");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment