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