ply.lex会解析同一个令牌吗?

时间:2014-07-13 16:36:06

标签: python parsing lexical-analysis ply lexical

我正在阅读lexical parsing文档,以便我可以解析一些参数,并且我完全按照文档创建了一个解析器。这是整个代码:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import ply.lex as lex

args = ['[watashi]', '[anata]>500', '[kare]>400&&[kare]<800']

tokens = ('NUMBER', 'EXPRESSION', 'AND', 'LESS', 'MORE')

t_EXPRESSION = r'\[.*\]'
t_AND = r'&&'
t_LESS = r'<'
t_MORE = r'>'
t_ignore = '\t'

def t_NUMBER(t):
    r'\d+'
    t.value = int(t.value)
    return t

def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

def t_error(t):
    print 'Illegal character "%s"' % t.value[0]
    t.lexer.skip(1)

lexer = lex.lex()

for i in args:
    lexer.input(i)
    while True:
        tok = lexer.token()
        if not tok: break
        print tok
    print '#############'

我只是创建了一个示例参数列表,我得到了这个输出:

LexToken(EXPRESSION,'[watashi]',1,0)
#############
LexToken(EXPRESSION,'[anata]',1,0)
LexToken(MORE,'>',1,7)
LexToken(NUMBER,500,1,8)
#############
LexToken(EXPRESSION,'[kare]>400&&[kare]',1,0)
LexToken(LESS,'<',1,18)
LexToken(NUMBER,800,1,19)
#############

第一个和第二个样本参数被正确解析,但第三个不是。第三个示例参数是EXPRESSION + LESS + NUMBER,而它必须是EXPRESSION + MORE + NUMBER + AND + EXPRESSION + LESS + NUMBER。所以我认为可能存在其中一个问题:

  • ply.lex只解析一个令牌:在上面的代码中,ply.lex无法解析两个单独的表达式,并返回最新的令牌作为其类型。 &#34; [KARE] GT; 400&安培;&安培; [KARE]&#34;是EXPRESSION,因为它以最新的EXPRESSION标记结束,该标记是第二个[kare]而800是NUMBER,因为它是最新的NUMBER标记。

    !!!或!!! !!!

  • t_EXPRESSION变量出错:我将此变量定义为&#34; [。*]&#34;获取这两个括号中的所有字符([])。第三个样本参数的第一个标记是&#34; [kare]&gt; 400&amp;&amp; [kare]&#34;因为它只是以这些括号开头和结尾,并且包含。*(每个字符),但我认为解释器会因为第一个而停在第一个(])字符中。

所以我找不到解决方法但在这里问。

总的来说,这就是我正在努力的事情

lexer.input("[kare]>400&&[kare]<800")
while True:
    tok = lexer.token()
    if not tok: break
    print tok

我得到了

LexToken(EXPRESSION,'[kare]>400&&[kare]',1,0)
LexToken(LESS,'<',1,18)
LexToken(NUMBER,800,1,19)

但我期待更像

的东西
LexToken(EXPRESSION,'[kare]',1.0)
LexToken(LESS,'>',?)
LexToken(NUMBER,400,?)
LexToken(AND,'&&',?)
LexToken(EXPRESSION,'[kare]',1,0)
LexToken(LESS,'<',1,18)
LexToken(NUMBER,800,1,19)

1 个答案:

答案 0 :(得分:2)

我想我看到了你的问题

t_EXPRESSION = r'\[.*\]'

是贪婪的,会匹配最大的匹配,即'[kare]>400&&[kare]'

而不是尝试

t_EXPRESSION = r'\[[^\]]*\]'

这只会匹配一个集,因为它找不到开括号([^\]])而不是任何东西(.

你也可以使用不贪心匹配

t_EXPRESSION = r'\[.*?\]'

?使其匹配尽可能少的字符而不是最大