pax_global_header00006660000000000000000000000064131006334710014510gustar00rootroot0000000000000052 comment=b989b7167b5ff582b844c00c26b8a7000b2fe835 speg-0.3/000077500000000000000000000000001310063347100123105ustar00rootroot00000000000000speg-0.3/.gitignore000066400000000000000000000000061310063347100142740ustar00rootroot00000000000000*.pyc speg-0.3/.travis.yml000066400000000000000000000001561310063347100144230ustar00rootroot00000000000000language: python python: - "2.7" - "3.4" script: python ./setup.py install && python -c "import speg" speg-0.3/LICENSE000066400000000000000000000015611310063347100133200ustar00rootroot00000000000000No-notice MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. speg-0.3/README.md000066400000000000000000000003701310063347100135670ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/avakar/speg.svg?branch=master)](https://travis-ci.org/avakar/speg) # speg A PEG-based parser interpreter with memoization. ## Installation The parser is tested on Python 2.7 and 3.4. pip install speg speg-0.3/setup.py000066400000000000000000000005301310063347100140200ustar00rootroot00000000000000#!/usr/bin/env python # coding: utf-8 from setuptools import setup setup( name='speg', version='0.3', description='A PEG-based parser interpreter with memoization', author='Martin Vejnár', author_email='vejnar.martin@gmail.com', url='https://github.com/avakar/speg', license='MIT', packages=['speg'], ) speg-0.3/speg/000077500000000000000000000000001310063347100132465ustar00rootroot00000000000000speg-0.3/speg/__init__.py000066400000000000000000000000411310063347100153520ustar00rootroot00000000000000from .peg import peg, ParseError speg-0.3/speg/peg.py000066400000000000000000000076531310063347100144060ustar00rootroot00000000000000import sys, re class ParseError(Exception): def __init__(self, msg, text, offset, line, col): self.msg = msg self.text = text self.offset = offset self.line = line self.col = col super(ParseError, self).__init__(msg, offset, line, col) if sys.version_info[0] == 2: _basestr = basestring else: _basestr = str def peg(s, r): p = _Peg(s) try: return p(r) except _UnexpectedError as e: offset = max(p._errors) err = p._errors[offset] raise ParseError(err.msg, s, offset, err.line, err.col) class _UnexpectedError(RuntimeError): def __init__(self, state, expr): self.state = state self.expr = expr class _PegState: def __init__(self, pos, line, col): self.pos = pos self.line = line self.col = col self.vars = {} self.commited = False class _PegError: def __init__(self, msg, line, col): self.msg = msg self.line = line self.col = col class _Peg: def __init__(self, s): self._s = s self._states = [_PegState(0, 1, 1)] self._errors = {} self._re_cache = {} def __call__(self, r, *args, **kw): if isinstance(r, _basestr): compiled = self._re_cache.get(r) if not compiled: compiled = re.compile(r) self._re_cache[r] = compiled st = self._states[-1] m = compiled.match(self._s[st.pos:]) if not m: self.error(expr=r, err=kw.get('err')) ms = m.group(0) st.pos += len(ms) nl_pos = ms.rfind('\n') if nl_pos < 0: st.col += len(ms) else: st.col = len(ms) - nl_pos st.line += ms[:nl_pos].count('\n') + 1 return ms else: kw.pop('err', None) return r(self, *args, **kw) def __repr__(self): pos = self._states[-1].pos vars = {} for st in self._states: vars.update(st.vars) return '_Peg(%r, %r)' % (self._s[:pos] + '*' + self._s[pos:], vars) @staticmethod def eof(p): if p._states[-1].pos != len(p._s): p.error() def error(self, err=None, expr=None): st = self._states[-1] if err is None: err = 'expected {!r}, found {!r}'.format(expr, self._s[st.pos:st.pos+4]) self._errors[st.pos] = _PegError(err, st.line, st.col) raise _UnexpectedError(st, expr) def get(self, key, default=None): for state in self._states[::-1]: if key in state.vars: return state.vars[key][0] return default def set(self, key, value): self._states[-1].vars[key] = value, False def set_global(self, key, value): self._states[-1].vars[key] = value, True def opt(self, *args, **kw): with self: return self(*args, **kw) def not_(self, s, *args, **kw): with self: self(s) self.error() def __enter__(self): self._states[-1].committed = False self._states.append(_PegState(self._states[-1].pos, self._states[-1].line, self._states[-1].col)) def __exit__(self, type, value, traceback): if type is None: self.commit() self._states.pop() return type == _UnexpectedError def commit(self): cur = self._states[-1] prev = self._states[-2] for key in cur.vars: val, g = cur.vars[key] if not g: continue if key in prev.vars: prev.vars[key] = val, prev.vars[key][1] else: prev.vars[key] = val, True prev.pos = cur.pos prev.line = cur.line prev.col = cur.col prev.committed = True def __nonzero__(self): return self._states[-1].committed __bool__ = __nonzero__