[pypy-svn] r14926 - in pypy/dist/pypy/interpreter/pyparser: . test

adim at codespeak.net adim at codespeak.net
Fri Jul 22 18:25:08 CEST 2005


Author: adim
Date: Fri Jul 22 18:25:06 2005
New Revision: 14926

Modified:
   pypy/dist/pypy/interpreter/pyparser/astbuilder.py
   pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
Log:
- implemented comparisons (+tests)
- started to implement multi expressions (+tests)



Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py	Fri Jul 22 18:25:06 2005
@@ -6,6 +6,7 @@
 import pypy.interpreter.pyparser.pytoken as tok
 
 ## these tests should be methods of the ast objects
+DEBUG_MODE = False
 
 def is_lvalue( ast_node ):
     return True
@@ -197,12 +198,48 @@
 def build_comparison( builder, nb ):
     L = get_atoms( builder, nb )
     l = len(L)
-    if l==1:
+    if l == 1:
         builder.push( L[0] )
         return
-    # TODO
-    assert False
-
+    else:
+        # a < b < c is transalted into:
+        # Compare(Name('a'), [('<', Name(b)), ('<', Name(c))])
+        left_token = L[0]
+        ops = []
+        for i in range(1, l, 2):
+            # if tok.name isn't in rpunct, then it should be
+            # 'is', 'is not', 'not' or 'not in' => tok.value
+            op_name = tok.tok_rpunct.get(L[i].name, L[i].value)
+            ops.append((op_name, L[i+1]))
+        builder.push(ast.Compare(L[0], ops))
+
+def build_comp_op(builder, nb):
+    """comp_op reducing has 2 different cases:
+     1. There's only one token to reduce => nothing to
+        do, just re-push it on the stack
+     2. Two tokens to reduce => it's either 'not in' or 'is not',
+        so we need to find out which one it is, and re-push a
+        single token
+
+    Note: reducing comp_op is needed because reducing comparison
+          rules is much easier when we can assume the comparison
+          operator is one and only one token on the stack (which
+          is not the case, by default, with 'not in' and 'is not')
+    """
+    L = get_atoms(builder, nb)
+    l = len(L)
+    # l==1 means '<', '>', '<=', etc.
+    if l == 1:
+        builder.push(L[0])
+    # l==2 means 'not in' or 'is not'
+    elif l == 2:
+        if L[0].value == 'not':
+            builder.push(TokenObject(tok.NAME, 'not in', None))
+        else:
+            builder.push(TokenObject(tok.NAME, 'is not', None))
+    else:
+        assert False, "TODO" # uh ?
+        
 def build_and_test( builder, nb ):
     return build_binary_expr( builder, nb, ast.And )
 
@@ -253,9 +290,12 @@
     l = len(L)
     nodes = []
     for n in range(0,l,2):
-        nodes.append(L[n])
+        node = L[n]
+        if isinstance(node, TokenObject) and node.name == tok.NEWLINE:
+            nodes.append(ast.Discard(ast.Const(None)))
+        else:
+            nodes.append(node)
     builder.push( ast.Stmt(nodes) )
-    return
 
 def build_single_input( builder, nb ):
     L = get_atoms( builder, nb )
@@ -353,6 +393,7 @@
     sym.xor_expr : build_xor_expr,
     sym.expr : build_expr,
     sym.comparison : build_comparison,
+    sym.comp_op : build_comp_op,
     sym.and_test : build_and_test,
     sym.test : build_test,
     sym.testlist : build_testlist,
@@ -446,8 +487,9 @@
                 self.push_rule( rule.codename, 1, source )
         else:
             self.push_rule( rule.codename, 1, source )
-        # show_stack(rule_stack, self.rule_stack)
-        # x = raw_input("Continue ?")
+        if DEBUG_MODE:
+            show_stack(rule_stack, self.rule_stack)
+            x = raw_input("Continue ?")
         return True
 
     def sequence(self, rule, source, elts_number):
@@ -463,8 +505,9 @@
                 self.push_rule( rule.codename, elts_number, source )
         else:
             self.push_rule( rule.codename, elts_number, source )
-        # show_stack(rule_stack, self.rule_stack)
-        # x = raw_input("Continue ?")
+        if DEBUG_MODE:
+            show_stack(rule_stack, self.rule_stack)
+            x = raw_input("Continue ?")
         return True
 
     def token(self, name, value, source):

Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py	Fri Jul 22 18:25:06 2005
@@ -44,13 +44,24 @@
     "a < b",
     "a > b",
     "a not in b",
+    "a is not b",
     "a in b",
+    "a is b",
     "3 < x < 5",
     "(3 < x) < 5",
+    "a < b < c < d",
+    "(a < b) < (c < d)",
+    "a < (b < c) < d",
+    ]
+comparison_tests = range(len(comparisons))
+# comparison_tests = [7]
+
+multiexpr = [
+    'a = b; c = d;',
+    'a = b = c = d',
+    'a = b\nc = d',
     ]
 
-comparison_tests = []
-failed_comparison_tests = range( len(comparisons) )
 def ast_parse_expr( expr ):
     builder = AstBuilder()
     PYTHON_PARSER.parse_source( expr, "single_input", builder )
@@ -67,6 +78,12 @@
     print "BUILT:", r1.rule_stack[-1]
     assert ast == r1.rule_stack[-1], 'failed on %r' % (expr)
 
+
+
+def test_multiexpr():
+    for expr in multiexpr:
+        yield check_expression, expr
+
 def test_backtracking_expressions():
     """tests for expressions that need backtracking"""
     for i in backtracking_tests:



More information about the Pypy-commit mailing list