refactor hpt_to_php to eliminate code duplication

This commit is contained in:
Meredith L. Patterson 2013-12-16 03:33:01 +01:00
parent aae140a420
commit ab23a29b0e
2 changed files with 48 additions and 77 deletions

View file

@ -11,21 +11,21 @@ class ActionTest extends PHPUnit_Framework_TestCase
} }
protected function setUp() 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() public function testSuccess()
{ {
/* $result1 = h_parse($this->parser, "ab"); */ $result1 = h_parse($this->parser, "ab");
/* $result2 = h_parse($this->parser, "AB"); */ $result2 = h_parse($this->parser, "AB");
/* $result3 = h_parse($this->parser, "aB"); */ $result3 = h_parse($this->parser, "aB");
/* $this->assertEquals("AB", $result1); */ $this->assertEquals("AB", $result1);
/* $this->assertEquals("AB", $result2); */ $this->assertEquals("AB", $result2);
/* $this->assertEquals("AB", $result3); */ $this->assertEquals("AB", $result3);
} }
public function testFailure() public function testFailure()
{ {
//$result = h_parse($this->parser, "XX"); $result = h_parse($this->parser, "XX");
//$this->assertEquals(NULL, $result); $this->assertEquals(NULL, $result);
} }
} }

View file

@ -1,4 +1,5 @@
%module hammer; %module hammer;
%include "exception.i";
%ignore HCountedArray_; %ignore HCountedArray_;
@ -13,7 +14,7 @@
%inline { %inline {
struct HParsedToken_; struct HParsedToken_;
struct HParseResult_; 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); static struct HParsedToken_* call_action(const struct HParseResult_ *p, void* user_data);
} }
@ -37,18 +38,17 @@
for (i=0; i<size; i++) { for (i=0; i<size; i++) {
zval **data; zval **data;
if (zend_hash_index_find(arr, i, (void**)&data) == FAILURE) { if (zend_hash_index_find(arr, i, (void**)&data) == FAILURE) {
// FIXME raise some error SWIG_exception(SWIG_IndexError, "index in parser array out of bounds");
arg1 = NULL; $1 = NULL;
} else { } else {
res = SWIG_ConvertPtr(*data, &($1[i]), SWIGTYPE_p_HParser_, 0 | 0); res = SWIG_ConvertPtr(*data, &($1[i]), SWIGTYPE_p_HParser_, 0 | 0);
if (!SWIG_IsOK(res)) { if (!SWIG_IsOK(res)) {
// TODO do we not *have* SWIG_TypeError? SWIG_exception(SWIG_TypeError, "that wasn't an HParser");
SWIG_exception_fail(res, "that wasn't an HParser");
} }
} }
} }
} else { } else {
// FIXME raise some error SWIG_exception(SWIG_TypeError, "that wasn't an array of HParsers");
$1 = NULL; $1 = NULL;
} }
} }
@ -74,43 +74,11 @@
*/ */
%typemap(out) struct HParseResult_* { %typemap(out) struct HParseResult_* {
if ($1 == NULL) { 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(); RETVAL_NULL();
} else { } else {
if ($1->ast == NULL) { hpt_to_php($result, $1->ast);
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;
}
}
} }
} }
/* /*
@ -126,41 +94,44 @@
%include "../swig/hammer.i"; %include "../swig/hammer.i";
%inline { %inline {
static zval* hpt_to_php(const HParsedToken *token) { void hpt_to_php(zval *return_value, const HParsedToken *token) {
zval *ret; if (!token) {
ALLOC_INIT_ZVAL(ret); RETVAL_NULL();
if (token == NULL) { return;
ZVAL_NULL(ret);
return ret;
} }
switch (token->token_type) { switch (token->token_type) {
case TT_NONE: case TT_NONE:
ZVAL_NULL(ret); RETVAL_NULL();
return ret; break;
case TT_BYTES: case TT_BYTES:
ZVAL_STRINGL(ret, (char*)token->token_data.bytes.token, token->token_data.bytes.len, 1); RETVAL_STRINGL((char*)token->token_data.bytes.token, token->token_data.bytes.len, 1);
return ret; break;
case TT_SINT: case TT_SINT:
ZVAL_LONG(ret, token->token_data.sint); RETVAL_LONG(token->token_data.sint);
return ret; break;
case TT_UINT: case TT_UINT:
ZVAL_LONG(ret, token->token_data.uint); RETVAL_LONG(token->token_data.uint);
return ret; break;
case TT_SEQUENCE: case TT_SEQUENCE:
array_init(ret); array_init(return_value);
for (int i=0; i < token->token_data.seq->used; i++) { 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: default:
/* if (token->token_type == h_tt_php) { */ 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 RETVAL_RESOURCE(token->token_data.user);
/* return return_value; */ } else {
/* } else { */ int res = 0;
/* // I guess that's a python thing */ res = SWIG_ConvertPtr(return_value, (void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0);
/* //return (zval*)SWIG_NewPointerObj((void*)token, SWIGTYPE_p_HParsedToken_, 0 | 0); */ if (!SWIG_IsOK(res)) {
/* // TODO: support registry */ SWIG_exception(SWIG_TypeError, "hpt_to_php: that wasn't an HParsedToken");
/* } */ }
// TODO: support registry
}
break; break;
} }
} }
@ -170,13 +141,13 @@
zval ret; zval ret;
// in PHP land, the HAction is passed by its name as a string // in PHP land, the HAction is passed by its name as a string
if (IS_STRING != Z_TYPE_P((zval*)user_data)) { 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 // FIXME throw some error
return NULL; return NULL;
} }
zval *callable; zval *callable;
callable = user_data; 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); int ok = call_user_function(EG(function_table), NULL, callable, &ret, 1, args TSRMLS_CC);
if (ok != SUCCESS) { if (ok != SUCCESS) {
printf("call_user_function failed"); printf("call_user_function failed");