Permalink
Browse files

Correct readme formatting.

  • Loading branch information...
1 parent 72d7068 commit 27a3c020ad190812f8e8edb51e3d603d65366a06 @erikrose committed Apr 5, 2012
Showing with 33 additions and 1 deletion.
  1. +1 −1 README.rst
  2. +19 −0 parsimonious/expressions.py
  3. +5 −0 parsimonious/grammar.py
  4. +8 −0 parsimonious/tests/test_grammar.py
View
@@ -23,7 +23,7 @@ Beyond speed, secondary goals include...
grammar.
Status
-------
+======
Not all the pieces of the grammar compiler are implemented yet, so it's not
suited for use unless you want to construct expression trees by hand, in Python
@@ -54,6 +54,10 @@ def parse(self, text):
cache = {}
node = self.match(text, cache=cache)
+ # TODO: Stop doing this, and instead introduce an Empty symbol that
+ # matches only at the EOF. Then we don't need both a public parse() and
+ # a match(), and you have the option of matching part of a string while
+ # still enjoying caching.
if node is None or node.end - node.start != len(text):
# If it was not a complete parse, return None:
return None
@@ -95,6 +99,21 @@ def match(self, text, pos=0, cache=dummy_cache):
return match
+class Empty(Expression):
+ """The empty expression, which matches only at the end of the text
+
+ Stick one of these at the end of your grammar if you want to make it match
+ only whole texts, You know, maybe a kwargs on parse() is easier to
+ understand for the non-having-studied-parsing among us. Is Empty useful
+ anywhere but the EOF?
+
+ """
+ def _uncached_match(self, text, pos=0, cache=dummy_cache):
+ """Return 0 if we're at the EOF, ``None`` otherwise."""
+ if pos == len(text):
+ return 0
+
+
class Literal(Expression):
"""A string literal
View
@@ -144,6 +144,11 @@ class _LazyReference(unicode):
class PegVisitor(NodeVisitor):
"""Turns a parse tree of a grammar definition into a map of ``Expression`` objects"""
+ quantifier_classes = {'?': Optional, '*': ZeroOrMore, '+': OneOrMore}
+
+ def visit_quantified(self, quantified, (atom, quantifier)):
+ return self.quantifier_classes[quantifier.text](atom)
+
def visit_rule(self, rule, (ws, label, _2, equals, _3, rhs, _4, eol)):
"""Assign a name to the Expression and return it."""
label = unicode(label) # Turn lazy reference back into text. # TODO: Remove backracking.
@@ -105,3 +105,11 @@ def test_undefined_rule(self):
"""Make sure we throw the right exception on undefined rules."""
tree = peg_grammar.parse('boy = howdy\n')
assert_raises(UndefinedLabel, PegVisitor().visit, tree)
+
+ def test_optional(self):
+ tree = peg_grammar.parse('boy = "howdy"?\n')
+ rules, default_rule = PegVisitor().visit(tree)
+
+ text = 'howdy'
+ eq_(default_rule.parse(text), Node('boy', text, 0, 5, children=[
+ ]))

0 comments on commit 27a3c02

Please sign in to comment.