Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r105:aeb1f133cab1 Date: 2014-11-29 01:35 +0100 http://bitbucket.org/cffi/creflect/changeset/aeb1f133cab1/
Log: The next part is a bit annoying and requires delaying the calls to cb->get_xxx_type() diff --git a/creflect/src/c_decl_parser.c b/creflect/src/c_decl_parser.c --- a/creflect/src/c_decl_parser.c +++ b/creflect/src/c_decl_parser.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <stdint.h> #include <assert.h> #include "creflect.h" @@ -35,11 +36,15 @@ TOK_VOID, }; +#define NUM_DELAY_SLOTS 5000 + typedef struct { enum crxp_token_e kind; const char *p; size_t size; crx_builder_t *cb; + intptr_t *delay_slots; + intptr_t all_delay_slots[NUM_DELAY_SLOTS]; } crxp_token_t; static int is_space(char x) @@ -134,48 +139,95 @@ } } -static crx_type_t *parse_sequel_right(crxp_token_t *tok, crx_type_t *t1) +static intptr_t *alloc_ds(crxp_token_t *tok, size_t num) { + intptr_t *result = tok->delay_slots; + if (num > (tok->all_delay_slots + NUM_DELAY_SLOTS - tok->delay_slots)) + abort(); // XXX out of memory + tok->delay_slots += num; + return result; +} + +static void parse_sequel(crxp_token_t *tok, intptr_t ds_end) +{ + while (tok->kind == TOK_STAR || tok->kind == TOK_CONST) { + alloc_ds(tok, 1)[0] = tok->kind; + next_token(tok); + } + + intptr_t *ds, *jump_slot = alloc_ds(tok, 1); + *jump_slot = ds_end; + + next_right_part: switch (tok->kind) { case TOK_OPEN_PAREN: - abort(); + /* just parentheses for grouping */ + next_token(tok); + + ds = tok->delay_slots; + parse_sequel(tok, *jump_slot); + *jump_slot = -(ds - tok->all_delay_slots); + + assert(tok->kind == TOK_CLOSE_PAREN); // XXX + next_token(tok); + goto next_right_part; case TOK_OPEN_BRACKET: next_token(tok); assert(tok->kind == TOK_INTEGER); // XXX - unsigned long long length = strtoull(tok->p, NULL, 10); + + uintptr_t length; + if (sizeof(uintptr_t) > sizeof(unsigned long)) + length = strtoull(tok->p, NULL, 10); + else + length = strtoul(tok->p, NULL, 10); next_token(tok); + assert(tok->kind == TOK_CLOSE_BRACKET); // XXX next_token(tok); - t1 = parse_sequel_right(tok, t1); - t1 = tok->cb->get_array_type(tok->cb, t1, (size_t)length); - break; + + ds = alloc_ds(tok, 3); + ds[0] = TOK_OPEN_BRACKET; + ds[1] = (intptr_t)length; + ds[2] = *jump_slot; + *jump_slot = -(ds - tok->all_delay_slots); + goto next_right_part; default: break; } - return t1; } -static crx_type_t *parse_sequel(crxp_token_t *tok, crx_type_t *t1) +static crx_type_t *fetch_delay_slots(crxp_token_t *tok, crx_type_t *t1, + intptr_t *delay_slot) { + tok->delay_slots = delay_slot; while (1) { - switch (tok->kind) { - - case TOK_STAR: - t1 = tok->cb->get_pointer_type(tok->cb, t1); - break; - - case TOK_CONST: - t1 = tok->cb->get_const_type(tok->cb, t1); - break; - - default: - return parse_sequel_right(tok, t1); + intptr_t tok_kind = *delay_slot++; + if (tok_kind > 0) { + switch (tok_kind) { + case TOK_END: + return t1; + case TOK_STAR: + t1 = tok->cb->get_pointer_type(tok->cb, t1); + break; + case TOK_CONST: + t1 = tok->cb->get_const_type(tok->cb, t1); + break; + case TOK_OPEN_BRACKET: /* array */ + { + uintptr_t length = (uintptr_t)*delay_slot++; + t1 = tok->cb->get_array_type(tok->cb, t1, length); + break; + } + default: + abort(); + } } - - next_token(tok); + else { + delay_slot = tok->all_delay_slots + (-tok_kind); + } } } @@ -192,29 +244,32 @@ break; default: tok->kind = TOK_ERROR; - return NULL; + return; } next_token(tok); if (is_const) { t1 = tok->cb->get_const_type(tok->cb, t1); } - return parse_sequel(tok, t1); + + intptr_t *orig = tok->delay_slots; + parse_sequel(tok, TOK_END); + return fetch_delay_slots(tok, t1, orig); } -crx_type_t *creflect_decl_parser(crx_builder_t *cb, const char **input) +const char *creflect_decl_parser(crx_builder_t *cb, const char *input, + crx_type_t **result) { crxp_token_t token; - crx_type_t *t1; token.kind = TOK_START; token.cb = cb; - token.p = *input; + token.p = input; token.size = 0; + token.delay_slots = token.all_delay_slots; next_token(&token); - t1 = parse_complete(&token); + *result = parse_complete(&token); if (token.kind == TOK_END) - return t1; - *input = token.p; - return NULL; + return NULL; + return token.p; } diff --git a/test/test_c_decl_parser.py b/test/test_c_decl_parser.py --- a/test/test_c_decl_parser.py +++ b/test/test_c_decl_parser.py @@ -8,10 +8,11 @@ int main(int argc, char *argv[]) { - const char *p = argv[1]; - crx_type_t *t1 = creflect_decl_parser(&maincb, &p); - if (t1 != NULL) + crx_type_t *t1; + const char *p = creflect_decl_parser(&maincb, argv[1], &t1); + if (p == NULL) { printf("%s\n", t1->text); + } else { printf("error: %s\n ", argv[1]); while (p > argv[1]) { @@ -39,6 +40,8 @@ def parse(input, expected_output): global executable got = subprocess.check_output([executable, input]) + print repr(input) + print got.rstrip() assert got == expected_output + '\n' def parse_error(input, expected_location): @@ -52,9 +55,9 @@ parse("int ** const", "CONST PTR PTR int") parse("int[2]", "ARRAY[2] int") parse("int*[2][3]", "ARRAY[2] ARRAY[3] PTR int") + parse("int(*)[2][3]", "PTR ARRAY[2] ARRAY[3] int") + parse("int(*[2])[3]", "ARRAY[2] PTR ARRAY[3] int") import py; py.test.skip("in-progress") - parse("int(*)[2][3]") - parse("int(*[2])[3]") parse("int()") parse("int(void)") parse("int(int)") _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit