3

我应该为令牌解析文档。标记可以是由字母数字字符组成的字符串,第一个字符是字母。

在下面的示例中,我想查看以下标记(zoo、abcd、moo、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

我将不胜感激。

附加示例:

我必须解析具有诸如 JOIN、ON、AS 等关键字的 SQL 之类的语言。我按照您的建议更改了“表”的定义。关键字“AS”的使用以及 AS 之后的别名标识符是可选的。对于“txt”中的第二行,没有使用“AS”和“alias”标识符。但我得到的输出如下。我不明白为什么会这样。

#!/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
4

1 回答 1

2

scanString 在那里通过输入字符串扫描匹配。它逐个字符地进行扫描。在位置 1,它尝试匹配token,但由于 JOIN 是保留字而失败,因此 NotAny 前瞻失败。然后 scanString 前进到位置 2。OIN 是一个完全有效的标记,因此它被报告为匹配。

如果您只想要令牌并希望 scanString 跳过关键字,请使用:

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

或者使用 parseString 而不是 scanString:

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

此外,Word 有一个 2 参数初始化程序,可以简化您对标识符的定义:

identifier = Word(alphas, alphanums + '_')
于 2013-05-29T23:29:41.827 回答