2013-05-29 75 views
1

我期望解析令牌文檔。令牌可以是由字母數字字符組成的字符串,第一個字符爲字母。排除預定義關鍵字列表中的令牌定義

在下面的例子,我想看看下面的標記(動物園,ABCD,哞,PQR,join6)

我的代碼看起來像下面

#!/usr/bin/env python 
from pyparsing import * 

reserved_words = (Keyword('JOIN') | Keyword('ON')) 
identifier = Combine(Word(alphas, exact=1) + Optional(Word(alphanums + '_'))) 
token = ~reserved_words + identifier 

txt = """ 
JOIN zoo ON abcd JOIN 
moo ON join6;""" 

for token, start, end in token.scanString(txt): 
    print token, start, end 

輸出,我看到的是:

['OIN'] 2 5 
['zoo'] 5 9 
['N'] 11 12 
['abcd'] 12 17 
['OIN'] 19 22 
['moo'] 22 26 
['N'] 28 29 
['join6'] 29 35 

我會很感激任何幫助。

附加例如:

我要解析SQL等,其具有像JOIN,關鍵字語言,等我換「表」你建議的方式定義。關鍵字'AS'的使用以及AS之後的別名標識符是可選的。對於「txt」中的第二行,不使用「AS」和「別名」標識符。但是我得到的輸出如下。我不明白爲什麼會發生這種情況。

#!/usr/bin/env python 
from pyparsing import * 

join_kw , on_kw, as_kw = map(lambda x: Keyword(x, caseless=True), ['JOIN' , 'ON', 'AS']) 
reserved_words = (join_kw | on_kw | as_kw) 
identifier = Combine(Word(alphas, exact=1) + Optional(Word(alphanums + '_'))) 
table = (reserved_words.suppress() | identifier) 
stmt = join_kw + table + Optional(as_kw) + Optional(identifier) + on_kw 
txt = """ 
JOIN zoo AS t ON abcd 
JOIN moo ON join6;""" 

for token, start, end in stmt.scanString(txt): 
    if len(token) != 0: 
     print token, start, end 

['JOIN', 'zoo', 'AS', 't', 'ON'] 1 17 

回答

2

scanString是通過輸入字符串掃描匹配。它進行字符掃描。在位置1處,它嘗試匹配token,並失敗,因爲JOIN是保留字,因此NotAny Lookahead失敗。然後scanString前進到位置2. OIN是一個完全有效的標記,因此它被報告爲匹配。

如果你只是想令牌,並希望scanString跳過的關鍵字,然後使用:

for token, start, end in (reserved_words.suppress() | token).scanString(txt): 

或者使用的,而不是scanString parseString:

for item in ZeroOrMore(reserved_words|token).parseString(txt): 

此外,Word有一個2參數初始值設定項,它將簡化您對標識符的定義:

identifier = Word(alphas, alphanums + '_') 
+0

Paul,謝謝您的澄清。您關於scanString的說明很有道理。我的意圖不僅是跳過保留關鍵字,而且還定義標識符的語法,以便排除關鍵字。讓我編輯原始帖子以提供更好的示例。 –

+0

定義標識符以排除關鍵字的最簡單方法是將標記從標記移動到標識符:標識符=〜reserved_words + Word(alphas,alphanums +'_')'。這是一種非常常見的pyparsing技術。 – PaulMcG

+0

感謝您的指導。這真的很有幫助。 –