]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/commitdiff
Change handling of spaces
authorOleg Broytman <phd@phdru.name>
Sat, 21 Jun 2014 23:27:13 +0000 (03:27 +0400)
committerOleg Broytman <phd@phdru.name>
Sat, 21 Jun 2014 23:27:13 +0000 (03:27 +0400)
AND/NOT/OR operators require spaces if subexpressions are not in
parentheses so ignoring whitespace no longer works.

parser/grammar
parser/parser.py
parser/test_parser.py

index 5a0c3d53a1a9c8d5f5d270804ed7f3150e0637bc..7c34096e3bdb10aaee6557185dcca6c60fb6d893 100644 (file)
@@ -26,9 +26,13 @@ NOT_OP : '!'
 SP1 : '[ \t]+'
 
 expression : NAME
 SP1 : '[ \t]+'
 
 expression : NAME
-           | expression AND_OP AND_OP expression
-           | expression AND_OP expression
-           | expression OR_OP OR_OP expression
-           | expression OR_OP expression
-           | NOT_OP expression
-           | '(' expression ')'
+           | expression SP0 AND_OP AND_OP SP0 expression
+           | expression SP0 AND_OP SP0 expression
+           | NOT_OP SP0 expression
+           | expression SP0 OR_OP OR_OP SP0 expression
+           | expression SP0 OR_OP SP0 expression
+           | '(' SP0 expression SP0 ')'
+
+SP0 : SP1 | empty
+
+empty :
index 1fb9903c62ee93794a22925678df963c728d4f2c..0af77f65f2e99054ff568226658e66b8e4d7608b 100644 (file)
@@ -4,7 +4,7 @@ from ply import lex, yacc
 
 literals = '()'
 
 
 literals = '()'
 
-tokens = ('NAME', 'AND_OP', 'OR_OP', 'NOT_OP')
+tokens = ('NAME', 'AND_OP', 'OR_OP', 'NOT_OP', 'SP1')
 
 t_NAME = '[a-z][a-z0-9_]*'
 
 
 t_NAME = '[a-z][a-z0-9_]*'
 
@@ -14,7 +14,7 @@ t_OR_OP = r'\|'
 
 t_NOT_OP = '!'
 
 
 t_NOT_OP = '!'
 
-t_ignore = '[ \t]+'
+t_SP1 = '[ \t]+'
 
 def t_error(t):
     """Avoid warnings on stderr"""
 
 def t_error(t):
     """Avoid warnings on stderr"""
@@ -26,28 +26,36 @@ def p_expression_name(p):
     p[0] = ('NAME', p[1])
 
 def p_expression_and_and(p):
     p[0] = ('NAME', p[1])
 
 def p_expression_and_and(p):
-    """expression : expression AND_OP AND_OP expression"""
-    p[0] = ('AND', p[1], p[4])
+    """expression : expression SP0 AND_OP AND_OP SP0 expression"""
+    p[0] = ('AND', p[1], p[6])
 
 def p_expression_and(p):
 
 def p_expression_and(p):
-    """expression : expression AND_OP expression"""
-    p[0] = ('AND', p[1], p[3])
+    """expression : expression SP0 AND_OP SP0 expression"""
+    p[0] = ('AND', p[1], p[5])
 
 def p_expression_not(p):
 
 def p_expression_not(p):
-    """expression : NOT_OP expression"""
-    p[0] = ('NOT', p[2])
+    """expression : NOT_OP SP0 expression"""
+    p[0] = ('NOT', p[3])
 
 def p_expression_or_or(p):
 
 def p_expression_or_or(p):
-    """expression : expression OR_OP OR_OP expression"""
-    p[0] = ('OR', p[1], p[4])
+    """expression : expression SP0 OR_OP OR_OP SP0 expression"""
+    p[0] = ('OR', p[1], p[6])
 
 def p_expression_or(p):
 
 def p_expression_or(p):
-    """expression : expression OR_OP expression"""
-    p[0] = ('OR', p[1], p[3])
+    """expression : expression SP0 OR_OP SP0 expression"""
+    p[0] = ('OR', p[1], p[5])
 
 def p_expression_parens(p):
 
 def p_expression_parens(p):
-    """expression : '(' expression ')'"""
-    p[0] = ('PARENS', p[2])
+    """expression : '(' SP0 expression SP0 ')'"""
+    p[0] = ('PARENS', p[3])
+
+def p_SP0(p):
+    """SP0 : SP1
+           | empty
+    """
+
+def p_empty(p):
+    """empty : """
 
 def p_error(p):
     """Avoid warnings on stderr"""
 
 def p_error(p):
     """Avoid warnings on stderr"""
index 628c9843b8d8509b11b7fc676e9452ef27329006..d7363c019b09a1a4bfd9df87c5577122de8ab17d 100755 (executable)
@@ -24,7 +24,7 @@ class TestParser(unittest.TestCase):
         self.assertEqual(parser.parse('!xxx&yyy&zzz|ooo'),
             ('OR', ('AND', ('AND', ('NOT', ('NAME', 'xxx')), ('NAME', 'yyy')), ('NAME', 'zzz')), ('NAME', 'ooo'))
         )
         self.assertEqual(parser.parse('!xxx&yyy&zzz|ooo'),
             ('OR', ('AND', ('AND', ('NOT', ('NAME', 'xxx')), ('NAME', 'yyy')), ('NAME', 'zzz')), ('NAME', 'ooo'))
         )
-        self.assertEqual(parser.parse('!(xxx && yyy)'),
+        self.assertEqual(parser.parse('!(xxx &&  yyy)'),
             ('NOT', ('PARENS', ('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))))
         )
         self.assertEqual(parser.parse('!(xxx || yyy)'),
             ('NOT', ('PARENS', ('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))))
         )
         self.assertEqual(parser.parse('!(xxx || yyy)'),