При использовании PLY (http://www.dabeaz.com/ply/) Я заметил, что это очень странная проблема: когда я использую токены типа &
для соединения, нижеприведенная программа работает, но когда я использую AND
там же, синтаксис PLY требует синтаксиса ошибка.Do AND, OR строки имеют особое значение в PLY?
Программа:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from ply import lex
import ply.yacc as yacc
parser = None
lexer = None
def flatten_list(lst):
flat = []
for x in lst:
if isinstance(x, list):
flat.extend(flatten_list(x))
else:
flat.append(x)
return flat
############## Tokenization ##############
tokens = (
'number',
'lparen',
'rparen',
'textw',
'titlew',
'qword',
'AND'
)
t_lparen = r'\('
t_rparen = r'\)'
t_textw = r'TEXTW:'
t_titlew = r'TITLEW:'
t_qword = r'\w+'
t_AND = r'AND'
def t_number(t):
r'\d+'
t.value = int(t.value)
return t
t_ignore = ' \t'
def t_error(t):
raise ValueError(
'Illegal character "{}" at position {}, query text: {}'.format(t.value[0], t.lexpos, t.lexer.lexdata))
lexer = lex.lex()
################# Parsing #################
def p_querylist_boolop(p):
"""querylist : subquery AND subquery"""
print >> sys.stderr, 'p_querylist', list(p)
p[0] = []
p[0].append(p[1])
p[0].append(p[3])
def p_subquery(p):
"""subquery : lparen querykw qwordseq rparen"""
print >> sys.stderr, 'p_subquery', list(p)
p[0] = flatten_list(p[3])
def p_querykw(p):
"""querykw : textw
| titlew"""
print >> sys.stderr, 'p_querykw', list(p)
p[0] = p[1]
def p_qwordseq(p):
"""qwordseq : qwordseq qword
| qwordseq number
| qword
| number"""
print >> sys.stderr, 'p_qwordseq', list(p)
if p[0]:
p[0].extend(p[1:])
else:
p[0] = p[1:]
def p_error(p):
global parser
if p:
tok = parser.token()
if tok:
msg = 'Syntax error in input, token "{}" at position {}, query text: {}'.format(tok.value, tok.lexpos,
lexer.lexdata)
raise ValueError(msg)
msg = 'Syntax error at the end of input, query text: {}'.format(lexer.lexdata)
raise ValueError(msg)
parser = yacc.yacc()
# parser = yacc.yacc(debug=0, write_tables=0)
def parse_query(q):
return parser.parse(q)
if __name__ == '__main__':
query_texts = ["""(TEXTW: one article) AND (TEXTW: two books)"""]
for qt in query_texts:
res = parse_query(qt)
print '***', res
Это дает:
ValueError: Syntax error in input, token "(" at position 19, query text: (TEXTW: abc) AND (TEXTW: aaa)
Однако, когда я изменяю следующее:
t_AND = r'&'
query_texts = ["""(TEXTW: one article) & (TEXTW: two books)"""]
..Это работает просто отлично:
*** [['one', 'article'], ['two', 'books']]
Проблема заключается в том, что строка «' AND' »будет сопоставляться с' t_qword = r '\ w +' 'в первом произведении' p_qwordseq', т. Е. Вам необходимо устранить неоднозначность вашей грамматики. –