Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit