[C++] better type mismatch error (#4623)

* better parse error

* pass str as a pointer instead of a reference for more efficient performance
This commit is contained in:
Masato Nagai 2018-02-17 01:32:50 +09:00 committed by Wouter van Oortmerssen
parent 36f8564846
commit 19c81b11b3
4 changed files with 26 additions and 24 deletions

View File

@ -647,11 +647,11 @@ class Parser : public ParserState {
size_t fieldn,
const StructDef *parent_struct_def);
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
BaseType req, bool *destmatch);
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
FLATBUFFERS_CHECKED_ERROR TokenError();
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e);
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
StructDef *LookupCreateStruct(const std::string &name,
bool create_if_new = true,

View File

@ -648,7 +648,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (token_ == '=') {
NEXT();
ECHECK(ParseSingleValue(field->value));
ECHECK(ParseSingleValue(&field->name, field->value));
if (!IsScalar(type.base_type) ||
(struct_def.fixed && field->value.constant != "0"))
return Error(
@ -878,11 +878,11 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
(token_ == kTokenIdentifier || token_ == kTokenStringConstant)) {
ECHECK(ParseHash(val, field));
} else {
ECHECK(ParseSingleValue(val));
ECHECK(ParseSingleValue(field ? &field->name : nullptr, val));
}
break;
}
default: ECHECK(ParseSingleValue(val)); break;
default: ECHECK(ParseSingleValue(field ? &field->name : nullptr, val)); break;
}
return NoError();
}
@ -1201,7 +1201,7 @@ CheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) {
attributes->Add(name, e);
if (Is(':')) {
NEXT();
ECHECK(ParseSingleValue(*e));
ECHECK(ParseSingleValue(&name, *e));
}
if (Is(')')) {
NEXT();
@ -1213,7 +1213,7 @@ CheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) {
return NoError();
}
CheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e,
CheckedError Parser::TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
BaseType req, bool *destmatch) {
bool match = dtoken == token_;
if (match) {
@ -1225,7 +1225,9 @@ CheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e,
} else {
return Error(std::string("type mismatch: expecting: ") +
kTypeNames[e.type.base_type] +
", found: " + kTypeNames[req]);
", found: " + kTypeNames[req] +
", name: " + (name ? *name : "") +
", value: " + e.constant);
}
}
NEXT();
@ -1310,13 +1312,13 @@ CheckedError Parser::TokenError() {
return Error("cannot parse value starting with: " + TokenToStringId(token_));
}
CheckedError Parser::ParseSingleValue(Value &e) {
CheckedError Parser::ParseSingleValue(const std::string *name, Value &e) {
// First see if this could be a conversion function:
if (token_ == kTokenIdentifier && *cursor_ == '(') {
auto functionname = attribute_;
NEXT();
EXPECT('(');
ECHECK(ParseSingleValue(e));
ECHECK(ParseSingleValue(name, e));
EXPECT(')');
// clang-format off
#define FLATBUFFERS_FN_DOUBLE(name, op) \
@ -1362,17 +1364,17 @@ CheckedError Parser::ParseSingleValue(Value &e) {
}
} else {
bool match = false;
ECHECK(TryTypedValue(kTokenIntegerConstant, IsScalar(e.type.base_type), e,
ECHECK(TryTypedValue(name, kTokenIntegerConstant, IsScalar(e.type.base_type), e,
BASE_TYPE_INT, &match));
ECHECK(TryTypedValue(kTokenFloatConstant, IsFloat(e.type.base_type), e,
ECHECK(TryTypedValue(name, kTokenFloatConstant, IsFloat(e.type.base_type), e,
BASE_TYPE_FLOAT, &match));
ECHECK(TryTypedValue(kTokenStringConstant,
ECHECK(TryTypedValue(name, kTokenStringConstant,
e.type.base_type == BASE_TYPE_STRING, e,
BASE_TYPE_STRING, &match));
auto istrue = IsIdent("true");
if (istrue || IsIdent("false")) {
attribute_ = NumToString(istrue);
ECHECK(TryTypedValue(kTokenIdentifier, IsBool(e.type.base_type), e,
ECHECK(TryTypedValue(name, kTokenIdentifier, IsBool(e.type.base_type), e,
BASE_TYPE_BOOL, &match));
}
if (!match) return TokenError();

Binary file not shown.

View File

@ -1,6 +1,6 @@
// automatically generated by the FlatBuffers compiler, do not modify
import * as NS9459827973991502386 from "./namespace_test1_generated";
import * as NS4989953370203581498 from "./namespace_test1_generated";
/**
* @constructor
*/
@ -39,24 +39,24 @@ static getRootAsTableInFirstNS(bb:flatbuffers.ByteBuffer, obj?:TableInFirstNS):T
* @param {NamespaceA.NamespaceB.TableInNestedNS=} obj
* @returns {NamespaceA.NamespaceB.TableInNestedNS|null}
*/
fooTable(obj?:NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS|null {
fooTable(obj?:NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS):NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS|null {
var offset = this.bb!.__offset(this.bb_pos, 4);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
return offset ? (obj || new NS4989953370203581498.NamespaceA.NamespaceB.TableInNestedNS).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
};
/**
* @returns {NamespaceA.NamespaceB.EnumInNestedNS}
*/
fooEnum():NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS {
fooEnum():NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS {
var offset = this.bb!.__offset(this.bb_pos, 6);
return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb!.readInt8(this.bb_pos + offset)) : NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A;
return offset ? /** @type {NamespaceA.NamespaceB.EnumInNestedNS} */ (this.bb!.readInt8(this.bb_pos + offset)) : NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS.A;
};
/**
* @param {NamespaceA.NamespaceB.EnumInNestedNS} value
* @returns {boolean}
*/
mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
mutate_foo_enum(value:NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS):boolean {
var offset = this.bb!.__offset(this.bb_pos, 6);
if (offset === 0) {
@ -71,9 +71,9 @@ mutate_foo_enum(value:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS
* @param {NamespaceA.NamespaceB.StructInNestedNS=} obj
* @returns {NamespaceA.NamespaceB.StructInNestedNS|null}
*/
fooStruct(obj?:NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS):NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS|null {
fooStruct(obj?:NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS):NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS|null {
var offset = this.bb!.__offset(this.bb_pos, 8);
return offset ? (obj || new NS9459827973991502386.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb!) : null;
return offset ? (obj || new NS4989953370203581498.NamespaceA.NamespaceB.StructInNestedNS).__init(this.bb_pos + offset, this.bb!) : null;
};
/**
@ -95,8 +95,8 @@ static addFooTable(builder:flatbuffers.Builder, fooTableOffset:flatbuffers.Offse
* @param {flatbuffers.Builder} builder
* @param {NamespaceA.NamespaceB.EnumInNestedNS} fooEnum
*/
static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS) {
builder.addFieldInt8(1, fooEnum, NS9459827973991502386.NamespaceA.NamespaceB.EnumInNestedNS.A);
static addFooEnum(builder:flatbuffers.Builder, fooEnum:NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS) {
builder.addFieldInt8(1, fooEnum, NS4989953370203581498.NamespaceA.NamespaceB.EnumInNestedNS.A);
};
/**