]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blobdiff - parser/parser.py
Fix handling of uppercase AND/OR
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
index 38c4cd236084d9bfb050214193503d64ced96c4c..cf463da5b63433082a0fd360b23586871232506e 100644 (file)
@@ -4,9 +4,9 @@ from ply import lex, yacc
 
 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_]*)|AND|OR|NOT'
 
 t_AND_OP = '&'
 
@@ -14,7 +14,7 @@ t_OR_OP = r'\|'
 
 t_NOT_OP = '!'
 
-t_ignore = '[ \t]+'
+t_SP1 = '[ \t]+'
 
 def t_error(t):
     """Avoid warnings on stderr"""
@@ -26,24 +26,76 @@ def p_expression_name(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):
-    """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):
-    """expression : NOT_OP expression"""
-    p[0] = ('NOT', p[2])
+def p_expression_op_word(p):
+    """expression : l_expression op_word r_expression"""
+    if p[2] in ('AND', 'and'):
+        p[0] = ('AND', p[1], p[3])
+    elif p[2] in ('OR', 'or'):
+        p[0] = ('OR', p[1], p[3])
+
+def p_expression_or_or(p):
+    """expression : expression SP0 OR_OP OR_OP SP0 expression"""
+    p[0] = ('OR', p[1], p[6])
 
 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_not(p):
+    """expression : NOT_OP SP0 expression"""
+    p[0] = ('NOT', p[3])
+
+def p_expression_in_parens(p):
+    """expression : expression_parens"""
+    p[0] = p[1]
+
+def p_l_expression(p):
+    """l_expression : expression_parens
+                    | expression SP1
+    """
+    if len(p) == 2:
+        p[0] = p[1]
+    elif len(p) == 3:
+        p[0] = p[1]
+    else:
+        raise ValueError(p)
+
+def p_r_expression(p):
+    """r_expression : expression_parens
+                    | SP1 expression
+    """
+    if len(p) == 2:
+        p[0] = p[1]
+    elif len(p) == 3:
+        p[0] = p[2]
+    else:
+        raise ValueError(p)
 
 def p_expression_parens(p):
-    """expression : '(' expression ')'"""
-    p[0] = ('PARENS', p[2])
+    """expression_parens : '(' SP0 expression SP0 ')'"""
+    p[0] = ('PARENS', p[3])
+
+def p_op_word(p):
+    """op_word : NAME"""
+    if p[1] in ('AND', 'and', 'OR', 'or'):
+        p[0] = p[1]
+    else:
+        raise SyntaxError
+
+def p_SP0(p):
+    """SP0 : SP1
+           | empty
+    """
+
+def p_empty(p):
+    """empty :"""
 
 def p_error(p):
     """Avoid warnings on stderr"""