changeset 7:b4844d42ed0f draft

Improve parsing of individual characters
author Lewin Bormann <lbo@spheniscida.de>
date Sun, 19 May 2019 14:31:40 +0200
parents e4b519f95d2d
children 07dfebce36c5
files arith_test.py combinators.py
diffstat 2 files changed, 14 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/arith_test.py	Sun May 19 14:15:45 2019 +0200
+++ b/arith_test.py	Sun May 19 14:31:40 2019 +0200
@@ -9,24 +9,29 @@
 from combinators import *
 
 class Parens(Parser):
+
     def parse(self, st):
         initial = st.index()
+
         p1, st = Operator('(').parse(st)
         print('pr', p1, st)
         if p1 is None:
             st.reset(initial)
             return None, st
+
         term, st = Term().parse(st)
         print('pr', term, st)
         if term is None:
             st.reset(initial)
             return None, st
+
         p2, st = Operator(')').parse(st)
         print('pr', p2, st)
         if p2 is None:
             print('No closing paren!')
             st.reset(initial)
             return None, st
+
         return term, st
 
 def Atom():
@@ -34,7 +39,8 @@
     return (Float() | Parens() | Regex('\w+'))
 
 def Operator(set):
-    return Last(Skip(Whitespace()) + CharSet(set))
+    """An operator or parenthesis."""
+    return Last(Skip(Whitespace()) + OneOf(set))
 
 class Product(Parser):
 
@@ -91,6 +97,7 @@
     return '({} {} {})'.format(pretty_print(tpl[0]), tpl[1], pretty_print(tpl[2]))
 
 def parse_and_print(expr):
+    """Parse an expression string and return a string of the parsing result."""
     parsed, st = Term().parse(ps(expr))
     if parsed is None:
         print('Parse error :(', st)
--- a/combinators.py	Sun May 19 14:15:45 2019 +0200
+++ b/combinators.py	Sun May 19 14:31:40 2019 +0200
@@ -272,7 +272,7 @@
         st.reset(initial)
         return (None, st)
 
-class CharSet(Parser):
+class OneOf(Parser):
     """Parse characters in the given set. Result is string or None, if none were parsed."""
     _set = None
 
@@ -286,8 +286,8 @@
 
     def parse(self, st):
         result = ''
-        while not st.finished() and st.peek() in self._set:
-            result += st.next()
+        if not st.finished() and st.peek() in self._set:
+            result = st.next()
         if len(result) == 0:
             return None, st
         return result, st
@@ -318,6 +318,9 @@
 
 # Small specific parsers.
 
+def CharSet(s):
+    return Repeat(OneOf(s), -1) >> (lambda l: ''.join(l))
+
 def Integer():
     """Return a parser that parses integers and results in an integer. Result is int."""
     return Last(Whitespace() + (CharSet('0123456789') >> int))