diff --git a/src/bindings/python/hammer_tests.py b/src/bindings/python/hammer_tests.py index 7a7d5f1af8b4b7b2e88319f34712341aa4abec30..587fbd5dbe052dcc279fb6f713e3208eeef33138 100644 --- a/src/bindings/python/hammer_tests.py +++ b/src/bindings/python/hammer_tests.py @@ -402,15 +402,15 @@ class TestEpsilonP3(unittest.TestCase): def test_failure(self): pass -# class TestAttrBool(unittest.TestCase): -# @classmethod -# def setUpClass(cls): -# cls.parser = h.h_attr_bool(h.h_many1(h.h_choice__a([h.h_ch("a"), h.h_ch("b")])), lambda x: x[0] == x[1]) -# def test_success(self): -# self.assertEqual(h.h_parse(self.parser, "aa"), ["a", "a"]) -# self.assertEqual(h.h_parse(self.parser, "bb"), ["b", "b"]) -# def test_failure(self): -# self.assertEqual(h.h_parse(self.parser, "ab"), None) +class TestAttrBool(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.parser = h.h_attr_bool(h.h_many1(h.h_choice__a([h.h_ch("a"), h.h_ch("b")])), lambda x: x[0] == x[1]) + def test_success(self): + self.assertEqual(h.h_parse(self.parser, "aa"), ("a", "a")) + self.assertEqual(h.h_parse(self.parser, "bb"), ("b", "b")) + def test_failure(self): + self.assertEqual(h.h_parse(self.parser, "ab"), None) class TestAnd1(unittest.TestCase): @classmethod diff --git a/src/bindings/swig/hammer.i b/src/bindings/swig/hammer.i index a2a8940ca114760616c6c56e022dddf06864290f..20661c85df05a13fb4d87d2c3565ea337b9e96b5 100644 --- a/src/bindings/swig/hammer.i +++ b/src/bindings/swig/hammer.i @@ -135,26 +135,28 @@ -/* -%typemap(in) (HPredicate* pred, void* user_data) { + +%typemap(in) (HPredicate pred, void* user_data) { Py_INCREF($input); $2 = $input; $1 = call_predicate; } -*/ + %typemap(in) (const HAction a, void* user_data) { Py_INCREF($input); $2 = $input; $1 = call_action; } -%inline { +%inline %{ + struct HParsedToken_; struct HParseResult_; static PyObject* hpt_to_python(const struct HParsedToken_ *token); static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data); - } + static int call_predicate(const struct HParseResult_ *p, void* user_data); + %} #else #warning no uint8_t* typemaps defined #endif @@ -164,6 +166,7 @@ #include "allocator.h" #include "hammer.h" #include "internal.h" +#include "glue.h" %} %include "allocator.h" %include "hammer.h" @@ -233,11 +236,30 @@ assert(ret != NULL); } // TODO: add reference to ret to parse-local data + // For now, just hold onto reference HParsedToken *tok = h_make(p->arena, h_tt_python, ret); return tok; } + static int call_predicate(const struct HParseResult_ *p, void* user_data) { + PyObject *callable = user_data; + PyObject *ret = PyObject_CallFunctionObjArgs(callable, + hpt_to_python(p->ast), + NULL); + int rret = 0; + if (ret == NULL) { + // TODO: throw exception + PyErr_Print(); + assert(ret != NULL); + } + // TODO: add reference to ret to parse-local data + rret = PyObject_IsTrue(ret); + Py_DECREF(ret); + return rret; + } + } + #endif