Added auto-construction, tidied h_ch a bit
This commit is contained in:
parent
a4dbfc61f2
commit
a99d7a18d1
1 changed files with 57 additions and 8 deletions
|
|
@ -4,7 +4,8 @@ import sys
|
||||||
|
|
||||||
_ffi = FFI()
|
_ffi = FFI()
|
||||||
|
|
||||||
## Types
|
# {{{ Types
|
||||||
|
|
||||||
_ffi.cdef("typedef struct HAllocator_ HAllocator;")
|
_ffi.cdef("typedef struct HAllocator_ HAllocator;")
|
||||||
_ffi.cdef("typedef struct HArena_ HArena;")
|
_ffi.cdef("typedef struct HArena_ HArena;")
|
||||||
_ffi.cdef("typedef int bool;")
|
_ffi.cdef("typedef int bool;")
|
||||||
|
|
@ -110,10 +111,12 @@ typedef struct HBenchmarkResults_ {
|
||||||
} HBenchmarkResults;
|
} HBenchmarkResults;
|
||||||
""")
|
""")
|
||||||
|
|
||||||
## Arena functions
|
# }}}
|
||||||
|
# {{{ Arena functions
|
||||||
_ffi.cdef("void* h_arena_malloc(HArena *arena, size_t count);")
|
_ffi.cdef("void* h_arena_malloc(HArena *arena, size_t count);")
|
||||||
_ffi.cdef("void h_arena_free(HArena *arena, void* ptr);")
|
_ffi.cdef("void h_arena_free(HArena *arena, void* ptr);")
|
||||||
|
# }}}
|
||||||
|
# {{{ cdefs
|
||||||
## The following section was generated by
|
## The following section was generated by
|
||||||
## $ perl ../desugar-header.pl <../../hammer.h |sed -e 's/.*/_ffi.cdef("&")/'
|
## $ 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);")
|
_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'])
|
libraries=['hammer'])
|
||||||
|
|
||||||
_lib.TT_PYTHON = _lib.TT_USER # TODO: Use the token type allocator from #45
|
_lib.TT_PYTHON = _lib.TT_USER # TODO: Use the token type allocator from #45
|
||||||
|
# }}}
|
||||||
class _DynamicScopeHolder(threading.local):
|
class _DynamicScopeHolder(threading.local):
|
||||||
"""A dynamically-scoped holder of python objects, which may or may not
|
"""A dynamically-scoped holder of python objects, which may or may not
|
||||||
otherwise appear in the object graph. Intended for use with CFFI """
|
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 = _ffi.cast("HParsedToken*", _lib.h_arena_malloc(_ffi.sizeof(parseResult.arena, "HParsedToken")))
|
||||||
hpt.token_type = _lib.TT_PYTHON
|
hpt.token_type = _lib.TT_PYTHON
|
||||||
hpt.user = cobj
|
hpt.user = cobj
|
||||||
hpt.bit_offset = 127;
|
hpt.bit_offset = chr(127)
|
||||||
hpt.index = 0;
|
hpt.index = 0
|
||||||
return hpt
|
return hpt
|
||||||
|
|
||||||
def _fromParseResult(cobj):
|
def _fromParseResult(cobj):
|
||||||
|
|
@ -311,6 +314,11 @@ class Parser(object):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def __mul__(self, count):
|
||||||
|
return repeat_n(self, count)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IndirectParser(Parser):
|
class IndirectParser(Parser):
|
||||||
def bind(self, inner):
|
def bind(self, inner):
|
||||||
_lib.h_bind_indirect(self._parser, inner._parser)
|
_lib.h_bind_indirect(self._parser, inner._parser)
|
||||||
|
|
@ -326,12 +334,20 @@ def token(token):
|
||||||
return Parser(_lib.h_token(token, len(token)), ())
|
return Parser(_lib.h_token(token, len(token)), ())
|
||||||
|
|
||||||
def ch(char):
|
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):
|
def ch_range(chr1, chr2):
|
||||||
if not isinstance(chr1, str) or not isinstance(chr2, str):
|
if not isinstance(chr1, str) or not isinstance(chr2, str):
|
||||||
raise TypeError("ch_range can't handle unicode")
|
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):
|
def int_range(parser, i1, i2):
|
||||||
if type(parser) != BitsParser:
|
if type(parser) != BitsParser:
|
||||||
|
|
@ -436,3 +452,36 @@ def run_test():
|
||||||
ch('3')),
|
ch('3')),
|
||||||
ch(','))
|
ch(','))
|
||||||
return p_test.parse("1,2,3")
|
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)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue