Added auto-construction, tidied h_ch a bit

This commit is contained in:
Dan Hirsch 2013-11-08 17:20:00 -05:00
parent 9d43244c2e
commit a31f2d31a4

View file

@ -4,7 +4,8 @@ import sys
_ffi = FFI()
## Types
# {{{ Types
_ffi.cdef("typedef struct HAllocator_ HAllocator;")
_ffi.cdef("typedef struct HArena_ HArena;")
_ffi.cdef("typedef int bool;")
@ -110,10 +111,12 @@ typedef struct HBenchmarkResults_ {
} HBenchmarkResults;
""")
## Arena functions
# }}}
# {{{ Arena functions
_ffi.cdef("void* h_arena_malloc(HArena *arena, size_t count);")
_ffi.cdef("void h_arena_free(HArena *arena, void* ptr);")
# }}}
# {{{ cdefs
## The following section was generated by
## $ perl ../desugar-header.pl <../../hammer.h |sed -e 's/.*/_ffi.cdef("&")/'
_ffi.cdef("HParseResult* h_parse(const HParser* parser, const uint8_t* input, size_t length);")
@ -216,7 +219,7 @@ _lib = _ffi.verify("#include <hammer/hammer.h>",
libraries=['hammer'])
_lib.TT_PYTHON = _lib.TT_USER # TODO: Use the token type allocator from #45
# }}}
class _DynamicScopeHolder(threading.local):
"""A dynamically-scoped holder of python objects, which may or may not
otherwise appear in the object graph. Intended for use with CFFI """
@ -263,8 +266,8 @@ def _toHParsedToken(arena, pyobj):
hpt = _ffi.cast("HParsedToken*", _lib.h_arena_malloc(_ffi.sizeof(parseResult.arena, "HParsedToken")))
hpt.token_type = _lib.TT_PYTHON
hpt.user = cobj
hpt.bit_offset = 127;
hpt.index = 0;
hpt.bit_offset = chr(127)
hpt.index = 0
return hpt
def _fromParseResult(cobj):
@ -311,6 +314,11 @@ class Parser(object):
else:
return None
def __mul__(self, count):
return repeat_n(self, count)
class IndirectParser(Parser):
def bind(self, inner):
_lib.h_bind_indirect(self._parser, inner._parser)
@ -326,12 +334,20 @@ def token(token):
return Parser(_lib.h_token(token, len(token)), ())
def ch(char):
return token(char)
"""Returns either a token or an int, depending on the type of the
argument"""
if isinstance(char, int):
return Parser(_lib.h_ch(char), ())
else:
return token(char)
def ch_range(chr1, chr2):
if not isinstance(chr1, str) or not isinstance(chr2, str):
raise TypeError("ch_range can't handle unicode")
return Parser(_lib.h_ch_range(chr1, chr2), ())
def my_action(pr):
# print "In action: ", pr
return pr
return action(Parser(_lib.h_ch_range(ord(chr1), ord(chr2)), ()), my_action)
def int_range(parser, i1, i2):
if type(parser) != BitsParser:
@ -436,3 +452,36 @@ def run_test():
ch('3')),
ch(','))
return p_test.parse("1,2,3")
# {{{ Automatic parser construction... python specific
# TODO: Implement Parsable metaclass, which requires the existence of
# a "parse" method.
# This is expected to be extended by user code. As a general rule,
# only provide auto-parsers for your own types.
AUTO_PARSERS = {
str: token,
unicode: token,
}
def _auto_seq(lst):
return sequence(*(auto_1(p, default_method=_auto_choice)
for p in lst))
def _auto_choice(lst):
return choice(*(auto_1(p, default_method=_auto_seq)
for p in lst))
def auto_1(arg, default_method=_auto_choice):
if isinstance(arg, Parser):
return arg
elif type(arg) in AUTO_PARSERS:
return AUTO_PARSERS[type(arg)](arg)
else:
return default_method(arg)
def auto(*args):
return auto_1(args, default_method=_auto_choice)
# }}}