static const struct token *tok_take_if(const struct token **toks, const char *target) { if (tok_is(toks, target)) return tok_take(toks); return NULL; }
/* enum ... */ static bool tok_take_enum(struct parse_state *ps) { size_t n = 0; struct cdump_type *e; const char *name; name = tok_take_ident(ps->defs, &ps->toks); if (!name) { complain(ps, "Expected enum name"); return false; } e = get_type(ps->defs, CDUMP_ENUM, name); /* Duplicate name? */ if (type_defined(e)) { complain(ps, "enum already defined"); return false; } if (!tok_take_if(&ps->toks, "{")) { complain(ps, "Expected { after enum name"); return false; } e->u.enum_vals = tal_arr(e, struct cdump_enum_val, n); do { struct cdump_enum_val *v; /* GCC extension: comma and end of enum */ if (tok_is(&ps->toks, "}")) break; tal_resize(&e->u.enum_vals, n+1); v = &e->u.enum_vals[n++]; v->name = tok_take_ident(e, &ps->toks); if (!v->name) { complain(ps, "Expected enum value name"); return false; } if (tok_take_if(&ps->toks, "=")) { v->value = tok_take_until(e, &ps->toks, ",}"); if (!v->value) { complain(ps, "Expected , or } to end value"); return false; } } else v->value = NULL; } while (tok_take_if(&ps->toks, ",")); if (tok_take_if(&ps->toks, "}") && tok_take_if(&ps->toks, ";")) return true; complain(ps, "Expected }; at end of enum"); return false; }
TEST(Lexer, DefaultTest) { std::string source = "VAR{\n" "i:int;\n" "i:float;\n" "}\n" "GO{\n" "i=1;\n" "}"; std::vector<Token> toks = tokenize(source); ASSERT_TRUE(tok_is(toks[0], token::VAR, 1, 1)); ASSERT_TRUE(tok_is(toks[1], token::LF_CR_BRACKET, 1, 4)); ASSERT_TRUE(tok_is(toks[2], token::IDENTIFIER, 2, 1)); ASSERT_TRUE(tok_is(toks[3], token::COLON, 2, 2)); ASSERT_TRUE(tok_is(toks[4], token::TYPE, 2, 3)); ASSERT_TRUE(tok_is(toks[5], token::SEMICOLON, 2, 6)); ASSERT_TRUE(tok_is(toks[6], token::IDENTIFIER, 3, 1)); ASSERT_TRUE(tok_is(toks[7], token::COLON, 3, 2)); ASSERT_TRUE(tok_is(toks[8], token::TYPE, 3, 3)); ASSERT_TRUE(tok_is(toks[9], token::SEMICOLON, 3, 8)); ASSERT_TRUE(tok_is(toks[10], token::RT_CR_BRACKET, 4, 1)); ASSERT_TRUE(tok_is(toks[11], token::GO, 5, 1)); ASSERT_TRUE(tok_is(toks[12], token::LF_CR_BRACKET, 5, 3)); ASSERT_TRUE(tok_is(toks[13], token::IDENTIFIER, 6, 1)); ASSERT_TRUE(tok_is(toks[14], token::ASSIGN, 6, 2)); ASSERT_TRUE(tok_is(toks[15], token::INT_LITERAL, 6, 3)); ASSERT_TRUE(tok_is(toks[16], token::SEMICOLON, 6, 4)); ASSERT_TRUE(tok_is(toks[17], token::RT_CR_BRACKET, 7, 1)); ASSERT_TRUE(tok_is(toks[18], token::END, 7, 2)); }
/* struct|union ... */ static bool tok_take_conglom(struct parse_state *ps, enum cdump_type_kind conglom_kind) { struct cdump_type *e; const char *name; size_t n; assert(conglom_kind == CDUMP_STRUCT || conglom_kind == CDUMP_UNION); name = tok_take_ident(ps->defs, &ps->toks); if (!name) { complain(ps, "Invalid struct/union name"); return false; } e = get_type(ps->defs, conglom_kind, name); if (type_defined(e)) { complain(ps, "Type already defined"); return false; } if (!tok_take_if(&ps->toks, "{")) { complain(ps, "Expected { for struct/union"); return false; } e->u.members = tal_arr(e, struct cdump_member, n = 0); while (!tok_is(&ps->toks, "}")) { struct cdump_type *basetype; const struct token *quals; unsigned int num_quals = 0; /* Anything can have these prepended. */ quals = ps->toks; while (tok_take_if(&ps->toks, "const") || tok_take_if(&ps->toks, "volatile")) num_quals++; /* eg. "struct foo" or "varint_t" */ if (!tok_take_type(ps, &basetype)) { complain(ps, "Expected typename inside struct/union"); return false; } do { struct cdump_member *m; tal_resize(&e->u.members, n+1); m = &e->u.members[n++]; m->type = basetype; if (num_quals) { m->qualifiers = string_of_toks(e, quals, quals + num_quals); } else m->qualifiers = NULL; /* May have multiple asterisks. */ while (tok_take_if(&ps->toks, "*")) m->type = ptr_of(ps, m->type); m->name = tok_take_ident(e, &ps->toks); if (!m->name) { complain(ps, "Expected name for member"); return false; } /* May be an array. */ while (tok_take_if(&ps->toks, "[")) { if (!tok_take_array(ps, &m->type)) return false; } } while (tok_take_if(&ps->toks, ",")); if (!tok_take_if(&ps->toks, ";")) { complain(ps, "Expected ; at end of member"); return false; } } if (tok_take_if(&ps->toks, "}") && tok_take_if(&ps->toks, ";")) return true; complain(ps, "Expected }; at end of struct/union"); return false; }