]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blob - parser/parser.py
Allow ' OR ' and ' or '
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / parser.py
1 # Parse query
2
3 from ply import lex, yacc
4
5 literals = '()'
6
7 tokens = ('NAME', 'AND_OP', 'OR_OP', 'NOT_OP', 'SP1')
8
9 t_NAME = '[a-z][a-z0-9_]*'
10
11 t_AND_OP = '&'
12
13 t_OR_OP = r'\|'
14
15 t_NOT_OP = '!'
16
17 t_SP1 = '[ \t]+'
18
19 def t_error(t):
20     """Avoid warnings on stderr"""
21
22 lexer = lex.lex()
23
24 def p_expression_name(p):
25     """expression : NAME"""
26     p[0] = ('NAME', p[1])
27
28 def p_expression_and_and(p):
29     """expression : expression SP0 AND_OP AND_OP SP0 expression"""
30     p[0] = ('AND', p[1], p[6])
31
32 def p_expression_and(p):
33     """expression : expression SP0 AND_OP SP0 expression"""
34     p[0] = ('AND', p[1], p[5])
35
36 def p_expression_op_word(p):
37     """expression : l_expression op_word r_expression"""
38     if p[2] in ('AND', 'and'):
39         p[0] = ('AND', p[1], p[3])
40     elif p[2] in ('OR', 'or'):
41         p[0] = ('OR', p[1], p[3])
42
43 def p_expression_not(p):
44     """expression : NOT_OP SP0 expression"""
45     p[0] = ('NOT', p[3])
46
47 def p_expression_or_or(p):
48     """expression : expression SP0 OR_OP OR_OP SP0 expression"""
49     p[0] = ('OR', p[1], p[6])
50
51 def p_expression_or(p):
52     """expression : expression SP0 OR_OP SP0 expression"""
53     p[0] = ('OR', p[1], p[5])
54
55 def p_expression_in_parens(p):
56     """expression : expression_parens"""
57     p[0] = p[1]
58
59 def p_l_expression(p):
60     """l_expression : expression_parens
61                     | expression SP1
62     """
63     if len(p) == 2:
64         p[0] = p[1]
65     elif len(p) == 3:
66         p[0] = p[1]
67     else:
68         raise ValueError(p)
69
70 def p_r_expression(p):
71     """r_expression : expression_parens
72                     | SP1 expression
73     """
74     if len(p) == 2:
75         p[0] = p[1]
76     elif len(p) == 3:
77         p[0] = p[2]
78     else:
79         raise ValueError(p)
80
81 def p_expression_parens(p):
82     """expression_parens : '(' SP0 expression SP0 ')'"""
83     p[0] = ('PARENS', p[3])
84
85 def p_op_word(p):
86     """op_word : NAME"""
87     if p[1] in ('AND', 'and', 'OR', 'or'):
88         p[0] = p[1]
89     else:
90         raise SyntaxError
91
92 def p_SP0(p):
93     """SP0 : SP1
94            | empty
95     """
96
97 def p_empty(p):
98     """empty :"""
99
100 def p_error(p):
101     """Avoid warnings on stderr"""
102     yacc.restart()
103
104 precedence = (
105     ('left', 'OR_OP'),
106     ('left', 'AND_OP'),
107     ('right', 'NOT_OP'),
108 )
109
110 parser = yacc.yacc()