Commit 92c4aef5 authored by Tianon Gravi's avatar Tianon Gravi

Update upstream source from tag 'upstream/0.7.7'

Update to upstream version '0.7.7'
with Debian dir c48cf8670ae1630b489814e0fcd015d087994cbd
parents ecdcb5d4 125bb2c4
Metadata-Version: 1.0
Name: rply
Version: 0.7.4
Version: 0.7.7
Summary: A pure Python Lex/Yacc that works with RPython
Home-page: UNKNOWN
Author: Alex Gaynor
Author-email: alex.gaynor@gmail.com
License: UNKNOWN
License: BSD 3-Clause License
Description: RPLY
====
.. image:: https://secure.travis-ci.org/alex/rply.png
:target: https://travis-ci.org/alex/rply
Welcome to RPLY! A pure python parser generator, that also works with RPython.
Welcome to RPLY! A pure Python parser generator, that also works with RPython.
It is a more-or-less direct port of David Beazley's awesome PLY, with a new
public API, and RPython support.
......@@ -118,7 +118,7 @@ Description: RPLY
Python compatibility
--------------------
RPly is tested and known to work under Python 2.6, 2.7, 3.1, and 3.2. It is
RPly is tested and known to work under Python 2.6, 2.7, 3.4+, and PyPy. It is
also valid RPython for PyPy checkouts from ``6c642ae7a0ea`` onwards.
Links
......@@ -128,6 +128,6 @@ Description: RPLY
* `PyPI releases <https://pypi.python.org/pypi/rply>`_
* `Talk at PyCon US 2013: So you want to write an interpreter? <http://pyvideo.org/video/1694/so-you-want-to-write-an-interpreter>`_
.. _`online`: https://rply.readthedocs.org/
.. _`online`: https://rply.readthedocs.io/
Platform: UNKNOWN
......@@ -4,7 +4,7 @@ RPLY
.. image:: https://secure.travis-ci.org/alex/rply.png
:target: https://travis-ci.org/alex/rply
Welcome to RPLY! A pure python parser generator, that also works with RPython.
Welcome to RPLY! A pure Python parser generator, that also works with RPython.
It is a more-or-less direct port of David Beazley's awesome PLY, with a new
public API, and RPython support.
......@@ -110,7 +110,7 @@ exception. It receives the ``Token`` object that the parser errored on.
Python compatibility
--------------------
RPly is tested and known to work under Python 2.6, 2.7, 3.1, and 3.2. It is
RPly is tested and known to work under Python 2.6, 2.7, 3.4+, and PyPy. It is
also valid RPython for PyPy checkouts from ``6c642ae7a0ea`` onwards.
Links
......@@ -120,4 +120,4 @@ Links
* `PyPI releases <https://pypi.python.org/pypi/rply>`_
* `Talk at PyCon US 2013: So you want to write an interpreter? <http://pyvideo.org/video/1694/so-you-want-to-write-an-interpreter>`_
.. _`online`: https://rply.readthedocs.org/
.. _`online`: https://rply.readthedocs.io/
Metadata-Version: 1.0
Name: rply
Version: 0.7.4
Version: 0.7.7
Summary: A pure Python Lex/Yacc that works with RPython
Home-page: UNKNOWN
Author: Alex Gaynor
Author-email: alex.gaynor@gmail.com
License: UNKNOWN
License: BSD 3-Clause License
Description: RPLY
====
.. image:: https://secure.travis-ci.org/alex/rply.png
:target: https://travis-ci.org/alex/rply
Welcome to RPLY! A pure python parser generator, that also works with RPython.
Welcome to RPLY! A pure Python parser generator, that also works with RPython.
It is a more-or-less direct port of David Beazley's awesome PLY, with a new
public API, and RPython support.
......@@ -118,7 +118,7 @@ Description: RPLY
Python compatibility
--------------------
RPly is tested and known to work under Python 2.6, 2.7, 3.1, and 3.2. It is
RPly is tested and known to work under Python 2.6, 2.7, 3.4+, and PyPy. It is
also valid RPython for PyPy checkouts from ``6c642ae7a0ea`` onwards.
Links
......@@ -128,6 +128,6 @@ Description: RPLY
* `PyPI releases <https://pypi.python.org/pypi/rply>`_
* `Talk at PyCon US 2013: So you want to write an interpreter? <http://pyvideo.org/video/1694/so-you-want-to-write-an-interpreter>`_
.. _`online`: https://rply.readthedocs.org/
.. _`online`: https://rply.readthedocs.io/
Platform: UNKNOWN
from rply.errors import ParsingError
from rply.errors import LexingError, ParsingError
from rply.lexergenerator import LexerGenerator
from rply.parsergenerator import ParserGenerator
from rply.token import Token
__version__ = '0.7.7'
__all__ = [
"LexerGenerator", "ParserGenerator", "ParsingError", "Token"
"LexerGenerator", "LexingError", "ParserGenerator", "ParsingError",
"Token",
]
......@@ -16,6 +16,9 @@ class LexingError(Exception):
"""
return self.source_pos
def __repr__(self):
return 'LexingError(%r, %r)' % (self.message, self.source_pos)
class ParsingError(Exception):
"""
......@@ -31,6 +34,9 @@ class ParsingError(Exception):
"""
return self.source_pos
def __repr__(self):
return 'ParsingError(%r, %r)' % (self.message, self.source_pos)
class ParserGeneratorWarning(Warning):
pass
......@@ -32,13 +32,17 @@ class LexerStream(object):
return match.start - last_nl
def next(self):
if self.idx >= len(self.s):
raise StopIteration
for rule in self.lexer.ignore_rules:
match = rule.matches(self.s, self.idx)
if match:
self._update_pos(match)
return self.next()
while True:
if self.idx >= len(self.s):
raise StopIteration
for rule in self.lexer.ignore_rules:
match = rule.matches(self.s, self.idx)
if match:
self._update_pos(match)
break
else:
break
for rule in self.lexer.rules:
match = rule.matches(self.s, self.idx)
if match:
......
......@@ -2,35 +2,44 @@ import re
try:
import rpython
from rpython.annotator import model
from rpython.annotator.bookkeeper import getbookkeeper
from rpython.rlib.objectmodel import instantiate, hlinvoke
from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.rsre import rsre_core
from rpython.rlib.rsre.rpy import get_code
from rpython.rtyper.annlowlevel import llstr, hlstr
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.lltypesystem.rlist import FixedSizeListRepr
from rpython.rtyper.lltypesystem.rstr import STR, string_repr
from rpython.rtyper.rmodel import Repr
from rpython.tool.pairtype import pairtype
except ImportError:
rpython = None
def we_are_translated():
return False
from rply.lexer import Lexer
class Rule(object):
_attrs_ = ['name', 'flags', '_pattern']
def __init__(self, name, pattern, flags=0):
self.name = name
self.re = re.compile(pattern, flags=flags)
if rpython:
self.flags = flags
self._pattern = get_code(pattern, flags)
def _freeze_(self):
return True
def matches(self, s, pos):
m = self.re.match(s, pos)
return Match(*m.span(0)) if m is not None else None
if not we_are_translated():
m = self.re.match(s, pos)
return Match(*m.span(0)) if m is not None else None
else:
assert pos >= 0
ctx = rsre_core.StrMatchContext(s, pos, len(s), self.flags)
matched = rsre_core.match_context(ctx, self._pattern)
if matched:
return Match(ctx.match_start, ctx.match_end)
else:
return None
class Match(object):
......@@ -42,7 +51,7 @@ class Match(object):
class LexerGenerator(object):
"""
r"""
A LexerGenerator represents a set of rules that match pieces of text that
should either be turned into tokens or ignored by the lexer.
......@@ -103,161 +112,3 @@ class LexerGenerator(object):
:class:`~rply.Token` instances.
"""
return Lexer(self.rules, self.ignore_rules)
if rpython:
class RuleEntry(ExtRegistryEntry):
_type_ = Rule
def compute_annotation(self, *args):
return SomeRule()
class SomeRule(model.SomeObject):
def rtyper_makekey(self):
return (type(self),)
def rtyper_makerepr(self, rtyper):
return RuleRepr(rtyper)
def method_matches(self, s_s, s_pos):
assert model.SomeString().contains(s_s)
assert model.SomeInteger(nonneg=True).contains(s_pos)
bk = getbookkeeper()
init_pbc = bk.immutablevalue(Match.__init__)
bk.emulate_pbc_call((self, "match_init"), init_pbc, [
model.SomeInstance(bk.getuniqueclassdef(Match)),
model.SomeInteger(nonneg=True),
model.SomeInteger(nonneg=True)
])
init_pbc = bk.immutablevalue(rsre_core.StrMatchContext.__init__)
bk.emulate_pbc_call((self, "str_match_context_init"), init_pbc, [
model.SomeInstance(
bk.getuniqueclassdef(rsre_core.StrMatchContext)
),
bk.newlist(model.SomeInteger(nonneg=True)),
model.SomeString(),
model.SomeInteger(nonneg=True),
model.SomeInteger(nonneg=True),
model.SomeInteger(nonneg=True),
])
match_context_pbc = bk.immutablevalue(rsre_core.match_context)
bk.emulate_pbc_call((self, "match_context"), match_context_pbc, [
model.SomeInstance(
bk.getuniqueclassdef(rsre_core.StrMatchContext)
),
])
return model.SomeInstance(
getbookkeeper().getuniqueclassdef(Match), can_be_None=True
)
def getattr(self, s_attr):
if s_attr.is_constant() and s_attr.const == "name":
return model.SomeString()
return super(SomeRule, self).getattr(s_attr)
class __extend__(pairtype(SomeRule, SomeRule)):
def union(self):
return SomeRule()
class RuleRepr(Repr):
def __init__(self, rtyper):
super(RuleRepr, self).__init__()
self.ll_rule_cache = {}
self.match_init_repr = rtyper.getrepr(
rtyper.annotator.bookkeeper.immutablevalue(Match.__init__)
)
self.match_context_init_repr = rtyper.getrepr(
rtyper.annotator.bookkeeper.immutablevalue(
rsre_core.StrMatchContext.__init__
)
)
self.match_context_repr = rtyper.getrepr(
rtyper.annotator.bookkeeper.immutablevalue(
rsre_core.match_context
)
)
list_repr = FixedSizeListRepr(
rtyper, rtyper.getrepr(model.SomeInteger(nonneg=True))
)
list_repr._setup_repr()
self.lowleveltype = lltype.Ptr(lltype.GcStruct(
"RULE",
("name", lltype.Ptr(STR)),
("code", list_repr.lowleveltype),
("flags", lltype.Signed),
))
def convert_const(self, rule):
if rule not in self.ll_rule_cache:
ll_rule = lltype.malloc(self.lowleveltype.TO)
ll_rule.name = llstr(rule.name)
code = get_code(rule.re.pattern)
ll_rule.code = lltype.malloc(
self.lowleveltype.TO.code.TO, len(code)
)
for i, c in enumerate(code):
ll_rule.code[i] = c
ll_rule.flags = rule.re.flags
self.ll_rule_cache[rule] = ll_rule
return self.ll_rule_cache[rule]
def rtype_getattr(self, hop):
s_attr = hop.args_s[1]
if s_attr.is_constant() and s_attr.const == "name":
v_rule = hop.inputarg(self, arg=0)
return hop.gendirectcall(LLRule.ll_get_name, v_rule)
return super(RuleRepr, self).rtype_getattr(hop)
def rtype_method_matches(self, hop):
[v_rule, v_s, v_pos] = hop.inputargs(
self, string_repr, lltype.Signed
)
c_MATCHTYPE = hop.inputconst(lltype.Void, Match)
c_MATCH_INIT = hop.inputconst(
lltype.Void, self.match_init_repr
)
c_MATCH_CONTEXTTYPE = hop.inputconst(
lltype.Void, rsre_core.StrMatchContext
)
c_MATCH_CONTEXT_INIT = hop.inputconst(
lltype.Void, self.match_context_init_repr
)
c_MATCH_CONTEXT = hop.inputconst(
lltype.Void, self.match_context_repr
)
return hop.gendirectcall(
LLRule.ll_matches,
c_MATCHTYPE, c_MATCH_INIT, c_MATCH_CONTEXTTYPE,
c_MATCH_CONTEXT_INIT, c_MATCH_CONTEXT, v_rule, v_s, v_pos
)
class LLRule(object):
@staticmethod
def ll_get_name(ll_rule):
return ll_rule.name
@staticmethod
def ll_matches(MATCHTYPE, MATCH_INIT, MATCH_CONTEXTTYPE,
MATCH_CONTEXT_INIT, MATCH_CONTEXT, ll_rule, s, pos):
s = hlstr(s)
assert pos >= 0
ctx = instantiate(MATCH_CONTEXTTYPE)
hlinvoke(
MATCH_CONTEXT_INIT, rsre_core.StrMatchContext.__init__,
ctx, ll_rule.code, hlstr(s), pos, len(s), ll_rule.flags
)
matched = hlinvoke(MATCH_CONTEXT, rsre_core.match_context, ctx)
if matched:
match = instantiate(MATCHTYPE)
hlinvoke(
MATCH_INIT, Match.__init__,
match, ctx.match_start, ctx.match_end
)
return match
else:
return None
import errno
import hashlib
import json
import os
import random
import string
import sys
import tempfile
import warnings
from appdirs import AppDirs
......@@ -37,9 +37,6 @@ class ParserGenerator(object):
self.tokens = tokens
self.productions = []
self.precedence = precedence
if cache_id is None:
# This ensures that we always go through the caching code.
cache_id = "".join(random.choice(string.ascii_letters) for _ in range(6))
self.cache_id = cache_id
self.error_handler = None
......@@ -175,27 +172,26 @@ class ParserGenerator(object):
g.compute_first()
g.compute_follow()
cache_dir = AppDirs("rply").user_cache_dir
cache_file = os.path.join(
cache_dir,
"%s-%s-%s.json" % (
self.cache_id, self.VERSION, self.compute_grammar_hash(g)
table = None
if self.cache_id is not None:
cache_dir = AppDirs("rply").user_cache_dir
cache_file = os.path.join(
cache_dir,
"%s-%s-%s.json" % (
self.cache_id, self.VERSION, self.compute_grammar_hash(g)
)
)
)
table = None
if os.path.exists(cache_file):
with open(cache_file) as f:
data = json.load(f)
if self.data_is_valid(g, data):
table = LRTable.from_cache(g, data)
if os.path.exists(cache_file):
with open(cache_file) as f:
data = json.load(f)
if self.data_is_valid(g, data):
table = LRTable.from_cache(g, data)
if table is None:
table = LRTable.from_grammar(g)
if not os.path.exists(cache_dir):
os.makedirs(cache_dir, mode=0o0700)
with open(cache_file, "w") as f:
json.dump(self.serialize_table(table), f)
if self.cache_id is not None:
self._write_cache(cache_dir, cache_file, table)
if table.sr_conflicts:
warnings.warn(
......@@ -217,6 +213,19 @@ class ParserGenerator(object):
)
return LRParser(table, self.error_handler)
def _write_cache(self, cache_dir, cache_file, table):
if not os.path.exists(cache_dir):
try:
os.makedirs(cache_dir, mode=0o0700)
except OSError as e:
if e.errno == errno.EROFS:
return
raise
with tempfile.NamedTemporaryFile(dir=cache_dir, delete=False, mode="w") as f:
json.dump(self.serialize_table(table), f)
os.rename(f.name, cache_file)
def digraph(X, R, FP):
N = dict.fromkeys(X, 0)
......@@ -494,15 +503,19 @@ class LRTable(object):
@classmethod
def compute_read_sets(cls, grammar, C, ntrans, nullable, add_count, cidhash, goto_cache):
FP = lambda x: cls.dr_relation(grammar, C, x, nullable, add_count, goto_cache)
R = lambda x: cls.reads_relation(C, x, nullable, add_count, cidhash, goto_cache)
return digraph(ntrans, R, FP)
return digraph(
ntrans,
R=lambda x: cls.reads_relation(C, x, nullable, add_count, cidhash, goto_cache),
FP=lambda x: cls.dr_relation(grammar, C, x, nullable, add_count, goto_cache)
)
@classmethod
def compute_follow_sets(cls, ntrans, readsets, includesets):
FP = lambda x: readsets[x]
R = lambda x: includesets.get(x, [])
return digraph(ntrans, R, FP)
return digraph(
ntrans,
R=lambda x: includesets.get(x, []),
FP=lambda x: readsets[x],
)
@classmethod
def dr_relation(cls, grammar, C, trans, nullable, add_count, goto_cache):
......
import sys
from collections import MutableMapping
if sys.version_info >= (3, 3):
from collections.abc import MutableMapping
else:
from collections import MutableMapping
class IdentityDict(MutableMapping):
......
[metadata]
license = BSD 3-Clause License
[wheel]
universal = 1
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0
......@@ -8,8 +8,8 @@ setup(
name="rply",
description="A pure Python Lex/Yacc that works with RPython",
long_description=readme,
# duplicated in docs/conf.py
version="0.7.4",
# duplicated in docs/conf.py and rply/__init__.py
version="0.7.7",
author="Alex Gaynor",
author_email="alex.gaynor@gmail.com",
packages=["rply"],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment