/* ':' must already be matched */ static void parse_type(fb_parser_t *P, fb_value_t *v) { fb_token_t *t = 0; fb_token_t *t0 = P->token; int vector = 0; v->type = vt_invalid; while ((t = optional(P, '['))) { ++vector; } if (vector > 1) { error_tok(P, t0, "vector type can only be one-dimensional"); } switch (P->token->id) { case tok_kw_int: case tok_kw_bool: case tok_kw_byte: case tok_kw_long: case tok_kw_uint: case tok_kw_float: case tok_kw_short: case tok_kw_ubyte: case tok_kw_ulong: case tok_kw_ushort: case tok_kw_double: v->t = P->token; v->type = vector ? vt_vector_type : vt_scalar_type; next(P); break; case tok_kw_string: v->t = P->token; v->type = vector ? vt_vector_string_type : vt_string_type; next(P); break; case LEX_TOK_ID: parse_ref(P, &v->ref); v->type = vector ? vt_vector_type_ref : vt_type_ref; break; case ']': error_tok(P, t, "vector type cannot be empty"); break; default: error_tok(P, t, "invalid type specifier"); break; } while (optional(P, ']') && vector--) { } if (vector) { error_tok_2(P, t, "vector type missing ']' to match", t0); } if ((t = optional(P, ']'))) { error_tok_2(P, t, "extra ']' not matching", t0); while (optional(P, ']')) { } } }
/* `struct` or `table` must already be matched. */ static void parse_compound_type(fb_parser_t *P, fb_compound_type_t *ct) { fb_token_t *t = 0; if (!(t = match(P, LEX_TOK_ID, "Declaration expected an identifier"))) { goto fail; } ct->symbol.ident = t; ct->metadata = parse_metadata(P); if (!(match(P, '{', "Declaration expected '{'"))) { goto fail; } t = P->token; /* Allow empty tables and structs. */ #if 0 if (P->token->id == '}') { error_tok(P, t, "table / struct declaration cannot be empty"); } #endif while (P->token->id != '}') { parse_field(P, fb_add_member(P, &ct->members)); if (P->failed >= FLATCC_MAX_ERRORS) { goto fail; } } if (!optional(P, '}') && t) { error_tok_2(P, P->token, "Declaration missing closing '}' to match", t); } revert_symbols(&ct->members); return; fail: recover(P, '}', 1); }
static fb_token_t *advance(fb_parser_t *P, long id, const char *msg, fb_token_t *peer) { /* * `advance` is generally used at end of statements so it is a * convenient place to get rid of rogue doc comments we can't attach * to anything meaningful. */ P->doc = 0; if (P->token->id != id) { error_tok_2(P, P->token, msg, peer); return P->token; } return next(P); }