diff --git a/src/bindings/php/Tests/ActionTest.php b/src/bindings/php/Tests/ActionTest.php index 0b7540d0e0ce367cf532e67c7bcb890817fa2982..619ea4a2b0daa4114f2187ddccc6fde47f0380c7 100644 --- a/src/bindings/php/Tests/ActionTest.php +++ b/src/bindings/php/Tests/ActionTest.php @@ -11,21 +11,21 @@ class ActionTest extends PHPUnit_Framework_TestCase } protected function setUp() { - //$this->parser = h_action(sequence(choice(ch("a"), ch("A")), choice(ch("b"), ch("B"))), "actTest"); + $this->parser = h_action(sequence(choice(ch("a"), ch("A")), choice(ch("b"), ch("B"))), "actTest"); } public function testSuccess() { - /* $result1 = h_parse($this->parser, "ab"); */ - /* $result2 = h_parse($this->parser, "AB"); */ - /* $result3 = h_parse($this->parser, "aB"); */ - /* $this->assertEquals("AB", $result1); */ - /* $this->assertEquals("AB", $result2); */ - /* $this->assertEquals("AB", $result3); */ + $result1 = h_parse($this->parser, "ab"); + $result2 = h_parse($this->parser, "AB"); + $result3 = h_parse($this->parser, "aB"); + $this->assertEquals("AB", $result1); + $this->assertEquals("AB", $result2); + $this->assertEquals("AB", $result3); } public function testFailure() { - //$result = h_parse($this->parser, "XX"); - //$this->assertEquals(NULL, $result); + $result = h_parse($this->parser, "XX"); + $this->assertEquals(NULL, $result); } } diff --git a/src/bindings/php/hammer.i b/src/bindings/php/hammer.i index 97d7e648e459e7ca101944258731d81d2ad97adf..67f6dd52a5e01294542d96588b3dc03fab09e6af 100644 --- a/src/bindings/php/hammer.i +++ b/src/bindings/php/hammer.i @@ -1,4 +1,5 @@ %module hammer; +%include "exception.i"; %ignore HCountedArray_; @@ -13,7 +14,7 @@ %inline { struct HParsedToken_; struct HParseResult_; - static zval* hpt_to_php(const struct HParsedToken_ *token); + void hpt_to_php(zval *return_value, const struct HParsedToken_ *token); static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data); } @@ -37,18 +38,17 @@ for (i=0; i<size; i++) { zval **data; if (zend_hash_index_find(arr, i, (void**)&data) == FAILURE) { - // FIXME raise some error - arg1 = NULL; + SWIG_exception(SWIG_IndexError, "index in parser array out of bounds"); + $1 = NULL; } else { res = SWIG_ConvertPtr(*data, &($1[i]), SWIGTYPE_p_HParser_, 0 | 0); if (!SWIG_IsOK(res)) { - // TODO do we not *have* SWIG_TypeError? - SWIG_exception_fail(res, "that wasn't an HParser"); + SWIG_exception(SWIG_TypeError, "that wasn't an HParser"); } } } } else { - // FIXME raise some error + SWIG_exception(SWIG_TypeError, "that wasn't an array of HParsers"); $1 = NULL; } } @@ -74,43 +74,11 @@ */ %typemap(out) struct HParseResult_* { if ($1 == NULL) { - // TODO: raise parse failure + /* If we want parse errors to be exceptions, this is the place to do it */ + //SWIG_exception(SWIG_TypeError, "typemap: should have been an HParseResult*, was NULL"); RETVAL_NULL(); } else { - if ($1->ast == NULL) { - RETVAL_NULL(); - } else { - switch($1->ast->token_type) { - case TT_NONE: - RETVAL_NULL(); - break; - case TT_BYTES: - RETVAL_STRINGL((char*)$1->ast->token_data.bytes.token, $1->ast->token_data.bytes.len, 1); - break; - case TT_SINT: - RETVAL_LONG($1->ast->token_data.sint); - break; - case TT_UINT: - RETVAL_LONG($1->ast->token_data.uint); - break; - case TT_SEQUENCE: - array_init($result); - for (int i=0; i < $1->ast->token_data.seq->used; i++) { - add_next_index_zval($result, hpt_to_php($1->ast->token_data.seq->elements[i])); - } - break; - default: - /* if (token->token_type == h_tt_php) { */ - /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, what else could I do with it? */ - /* return return_value; */ - /* } else { */ - /* // I guess that's a python thing */ - /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ - /* // TODO: support registry */ - /* } */ - break; - } - } + hpt_to_php($result, $1->ast); } } /* @@ -126,41 +94,44 @@ %include "../swig/hammer.i"; %inline { - static zval* hpt_to_php(const HParsedToken *token) { - zval *ret; - ALLOC_INIT_ZVAL(ret); - if (token == NULL) { - ZVAL_NULL(ret); - return ret; + void hpt_to_php(zval *return_value, const HParsedToken *token) { + if (!token) { + RETVAL_NULL(); + return; } switch (token->token_type) { case TT_NONE: - ZVAL_NULL(ret); - return ret; + RETVAL_NULL(); + break; case TT_BYTES: - ZVAL_STRINGL(ret, (char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); - return ret; + RETVAL_STRINGL((char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); + break; case TT_SINT: - ZVAL_LONG(ret, token->token_data.sint); - return ret; + RETVAL_LONG(token->token_data.sint); + break; case TT_UINT: - ZVAL_LONG(ret, token->token_data.uint); - return ret; + RETVAL_LONG(token->token_data.uint); + break; case TT_SEQUENCE: - array_init(ret); + array_init(return_value); for (int i=0; i < token->token_data.seq->used; i++) { - add_next_index_zval(ret, hpt_to_php(token->token_data.seq->elements[i])); + zval *tmp; + ALLOC_INIT_ZVAL(tmp); + hpt_to_php(tmp, token->token_data.seq->elements[i]); + add_next_index_zval(return_value, tmp); } - return ret; + break; default: - /* if (token->token_type == h_tt_php) { */ - /* ZEND_REGISTER_RESOURCE(return_value, token->token_data.user, le_swig__p_void); // it's a void*, wh - /* return return_value; */ - /* } else { */ - /* // I guess that's a python thing */ - /* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ - /* // TODO: support registry */ - /* } */ + if (token->token_type == h_tt_php) { + RETVAL_RESOURCE(token->token_data.user); + } else { + int res = 0; + res = SWIG_ConvertPtr(return_value, (void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); + if (!SWIG_IsOK(res)) { + SWIG_exception(SWIG_TypeError, "hpt_to_php: that wasn't an HParsedToken"); + } + // TODO: support registry + } break; } } @@ -170,13 +141,13 @@ zval ret; // in PHP land, the HAction is passed by its name as a string if (IS_STRING != Z_TYPE_P((zval*)user_data)) { - printf("user_data wasn't a string"); + printf("user_data wasn't a string\n"); // FIXME throw some error return NULL; } zval *callable; callable = user_data; - args[0] = hpt_to_php(p->ast); + hpt_to_php(args[0], p->ast); int ok = call_user_function(EG(function_table), NULL, callable, &ret, 1, args TSRMLS_CC); if (ok != SUCCESS) { printf("call_user_function failed");