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

Reply via email to