2016-09-21 1 views
0

PLY(http://www.dabeaz.com/ply/)を使用すると、私は非常に奇妙な問題があるように見えました。&のようなトークンを使用すると、以下のプログラムが動作しますが、ANDを同じ場所に使用すると、エラー。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) 

をしかし、私は次のように変更する場合:だけで正常に動作し..it

t_AND = r'&' 
query_texts = ["""(TEXTW: one article) & (TEXTW: two books)"""] 

*** [['one', 'article'], ['two', 'books']] 
+2

問題はおそらく、最初の 'p_qwordseq'プロダクションで文字列" AND "が' t_qword = r '\ w +' 'とマッチすることになります。つまり、文法を明確にする必要があります。 –

答えて

0

Plyはトークンの正規表現の順序付けに少し偏ったアプローチをしています。これは基本的にPython正規表現ライブラリに依存するためです。 numberトークンなどの関数で定義されたトークンは、表示される順序で認識され、多くの字句スキャナジェネレータとは異なり、Plyは最長一致を試みません。代入で定義されたトークン(他のすべてのトークンタイプ)は、関数よりも優先度が低く、(正規表現の)長さを短くすることによって、順番に配置されます。パターンr'AND'は、例えば、例えば、最初の3つの文字を認識するので、強く、などANDなどのキーワードトークンの変数割り当てスタイルを使用していないことを示唆している

プライマニュアル(4.3節)、ANDROGYNOUS、あなたはおそらくだろう変数になることを期待する。 単純なパターンの関数を使用して、まずすべてのキーワードと変数を単純な単語として認識し、辞書を使用して特定のキーワードを認識することをお勧めします。サンプルコードと少ない電文の説明は、Plyのマニュアル(上記で引用したセクション)にあります。

関連する問題