2013-05-29 34 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

感谢您的指导。这真的很有帮助。 –