0

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

#!/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 无法解析两个单独的表达式,它返回最新的标记作为其类型。"[kare]>400&&[kare]" 是 EXPRESSION,因为它以第二个 [kare] 的最新 EXPRESSION 令牌结尾,而 800 是 NUMBER,因为它是最新的 NUMBER 令牌。

    !!!或者 !!!

  • t_EXPRESSION 变量中有一个错误:我将此变量定义为“[.*]”以获取这两个括号 ([]) 中的所有字符。第三个示例参数的第一个标记是“[kare]>400&&[kare]”,因为它只是以这些括号开始和结束,并且在其中包含 .*(每个字符),但我认为解释器会在第一个 ( ]) 字符由于是第一个。

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

总的来说,这就是我正在努力解决的问题

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)
4

1 回答 1

2

我想我看到了你的问题

t_EXPRESSION = r'\[.*\]'

是贪婪的并且会匹配它可以匹配的最大匹配'[kare]>400&&[kare]'

而是尝试

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

这将只匹配一组,因为它寻找不开括号([^\]])而不是任何东西(.

你也可以使用不贪心匹配

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

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

于 2014-07-13T17:11:44.670 回答