Python PLY:非法字符'+';

Python PLY:非法字符'+';,python,regex,python-2.7,ply,Python,Regex,Python 2.7,Ply,我正在使用ply开发python解析器,我必须以以下形式解析输入: VAR VAR1 001 +000 000 000 000 其中,代码将创建一个名为VAR 1的变量,然后将值0赋给它 我为实例编写的正则表达式是: t_INST = r'[\+|-]0[ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9]' 但是,在运行我的程序时,PLY会打印以下内容: Illegal character '+'

我正在使用ply开发python解析器,我必须以以下形式解析输入:

VAR VAR1 001 
+000 000 000 000
其中,代码将创建一个名为VAR 1的变量,然后将值0赋给它

我为实例编写的正则表达式是:

t_INST = r'[\+|-]0[ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9]'
但是,在运行我的程序时,PLY会打印以下内容:

Illegal character '+'

复制机如下所示:

import ply.lex as lex

tokens = ['INST']
t_INST = r'[+-]0[ ](\d{3}[ ]){3}\d{3}';
t_ignore  = ' \t'
def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

lexer = lex.lex()

def parse(input_string):
    ret = []
    lexer.input (input_string)
    while True:
        tok = lexer.token()
        if not tok:
            break      # No more input
        ret.append((tok.type, tok.value))
    return ret

print parse("+0 000 000 000")

您不必在字符类中转义
+
。您可以使用:

t_INST = r'[+|-]0[ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9][ ][0-9][0-9][0-9]'
   this-----^
无论如何,您可以这样缩短正则表达式:

t_INST = r'[+|-]0[ ][0-9]{3}[ ][0-9]{3}[ ][0-9]{3}[ ][0-9]{3}'
甚至:

t_INST = r'[+|-]0[ ]([0-9]{3}[ ]){3}[0-9]{3}'
还注意到您使用了
[+-]
,这是一个字符类,不适用于替换,因此您必须将其更改为
[+-]

因此,最后一个正则表达式(使用
\d
作为
[0-9]
的快捷方式)是:

t_INST = r'[+-]0[ ](\d{3}[ ]){3}\d{3}'
顺便说一句,您的示例文本显示:

+000 000 000 000
但您使用的正则表达式与此匹配:

+0 000 000 000 000
因此,如果要匹配的数据是
+000
,则必须将正则表达式更改为:

t_INST = r'[+-](\d{3}[ ]){3}\d{3}'
该行:

print parse("+0 000 000 000")
与您声明的输入格式不匹配

VAR VAR1 001 
+000 000 000 000
如果实际数据的格式与
+0 000 000
相同,则实际需要:

t_INST = r'[+-]0\s(?:\d{3}\s){2}\d{3}'

…其输出为:
[('INST','+0 000')]

您应该使用\d表示字符,还应该使用{}表示重复序列:[\+-](?:\d{3}\s?{4}为什么使用反斜杠?您可能希望在正常的上下文中这样做,但在角色类中没有意义。实际上,除非
|
是有效的第一个字符,否则您可能也希望
[+-]
,而不是
[+-]
。顺便说一句,将您的复制器(同时尽可能保持最小)扩展到完整且可验证的程度会有所帮助,如中所示。现在,有人需要做相当多的工作来重现这个bug。请在问题中提供我的解析器的MVCE。或者至少在没有广告的地方(如果你使用的是adblock,你可能没有注意到pastebin.com上到处都是广告);这是一个很好的选择。这是我在回答中给出的正则表达式,使用
\s
作为快捷方式和非捕获组。这听起来更像是对我问题的评论。此外,对于OP的测试数据,您使用了
{2}
,并且应该是
{3}
,不,它确实应该是
{2}
。他们的评论对实际使用的数据格式具有误导性。(这就是为什么我花了大量的时间强迫他们提供一个真正的复制者,而不是直接写一个答案)…这里的问题(即,我选择写一个竞争性答案而不是评论这个答案的不良行为)你写了一个答案,但实际上没有一个真正的复制者,这可能会造成他们的问题,因此没有保证你真的知道OP的问题是什么。即使
re.compile(r'[\+\-]].match('+')
不起作用,我也同意有充分的理由进行推测,但事实并非如此:最初的代码很糟糕,但(可测试!)没有在最初给出的任何理由上被破坏……事实上,
re.compile(r'[\+-]0[\+]0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')。匹配('+0 000')
返回匹配项。