竞争正则表达式(竞争条件)
competing regular expressions (race condition)
我正在尝试使用 python PLY (lex/yacc) 来解析一种名为 'GRBL' 的语言。
GRBL 看起来像这样:
G00 X0.0 Y0.0 Z-1.0
G01 X1.0
..
'G' 代码告诉机器 'go'(或移动),坐标表示位置。
LEX 要求我们为每个可能的 'token'.
指定唯一的正则表达式
所以在这种情况下,我需要一个可以明确定义 'G00' 的正则表达式和一个可以明确定义 'G01' 等的正则表达式
显然一个人的第一个想法是 r'G00'
等等。
然而 G 代码是不精确的。 G可以是大写或小写,可以有前导零等
(g0, G00, g001 等)
所以 G00 的东西可能很简单:
r'[Gg]{1}0*'
对于 G01,我们可以
r'[Gg]{1}0*1'
但这不起作用。 G00 正确解析,但 G01 给出:
LexToken(G00,'G0',3,21)
Illegal character '1'
也就是说,lex 认为 G01 是一个 G0 标记,不知道如何处理 '1'。
这显然是某种贪婪匹配问题。
不幸的是,我无法使用“$”终止符指定字符串必须 'end' 和“1”
我意识到这对某些人来说可能看起来很简单,但我已经做了 3 个小时,但无法让它工作!有谁知道如何解决这个问题?
注意:完全没有理由在正则表达式中写 {1}
。这意味着前一个元素应该恰好重复一次,如果没有重复运算符就会发生这种情况。所以它所做的就是混淆正则表达式(并减慢匹配速度)。
但这不是你的问题。您的问题可能是 Ply 应用正则表达式的顺序。 Ply 通过将所有模式连接成一组备选方案来创建一个巨大的 Python 正则表达式:
(pattern1)|(pattern2)|(pattern3)|...|(patternz)
插入模式的顺序很重要,因为 Python“正则”表达式使用有序交替运算符(使它们在数学术语中实际上是不规则的,但这是一个附带问题)。所以一旦有一些替代匹配,下面的就更不用试了
Ply 手册定义了顺序:
- All tokens defined by functions are added in the same order as they appear in the lexer file.
- Tokens defined by strings are added next by sorting them in order of decreasing regular expression length (longer expressions are added first).
我猜你正在使用函数,所以模式是按文件中出现的顺序排列的,因为你的第二个模式——更长——如果它们被定义为字符串,将首先应用.但是没有看到您的实际文件,很难确定。
无论如何,Ply lexers 的传统智慧是使用尽可能少的模式,更喜欢将关键字映射到带有字典的标记。在 GRBL 的情况下,一种可能是使用 [Gg][0-9]+(\.[0-9]÷)?
作为模式,然后在语义操作中提取索引。
你的模式 [Gg]{1}0* 是通用的,它匹配 G00 和 G01 https://regex101.com/r/gkz0Wb/1
在第二种情况下,您只剩下单个字符 1.
您必须使此模式更具体,例如通过在结束模式 [Gg]{1}0*\s 添加空白字符
https://regex101.com/r/dsSFaG/1
我正在尝试使用 python PLY (lex/yacc) 来解析一种名为 'GRBL' 的语言。 GRBL 看起来像这样:
G00 X0.0 Y0.0 Z-1.0
G01 X1.0
..
'G' 代码告诉机器 'go'(或移动),坐标表示位置。
LEX 要求我们为每个可能的 'token'.
指定唯一的正则表达式所以在这种情况下,我需要一个可以明确定义 'G00' 的正则表达式和一个可以明确定义 'G01' 等的正则表达式
显然一个人的第一个想法是 r'G00'
等等。
然而 G 代码是不精确的。 G可以是大写或小写,可以有前导零等
(g0, G00, g001 等)
所以 G00 的东西可能很简单:
r'[Gg]{1}0*'
对于 G01,我们可以
r'[Gg]{1}0*1'
但这不起作用。 G00 正确解析,但 G01 给出:
LexToken(G00,'G0',3,21)
Illegal character '1'
也就是说,lex 认为 G01 是一个 G0 标记,不知道如何处理 '1'。 这显然是某种贪婪匹配问题。
不幸的是,我无法使用“$”终止符指定字符串必须 'end' 和“1”
我意识到这对某些人来说可能看起来很简单,但我已经做了 3 个小时,但无法让它工作!有谁知道如何解决这个问题?
注意:完全没有理由在正则表达式中写 {1}
。这意味着前一个元素应该恰好重复一次,如果没有重复运算符就会发生这种情况。所以它所做的就是混淆正则表达式(并减慢匹配速度)。
但这不是你的问题。您的问题可能是 Ply 应用正则表达式的顺序。 Ply 通过将所有模式连接成一组备选方案来创建一个巨大的 Python 正则表达式:
(pattern1)|(pattern2)|(pattern3)|...|(patternz)
插入模式的顺序很重要,因为 Python“正则”表达式使用有序交替运算符(使它们在数学术语中实际上是不规则的,但这是一个附带问题)。所以一旦有一些替代匹配,下面的就更不用试了
Ply 手册定义了顺序:
- All tokens defined by functions are added in the same order as they appear in the lexer file.
- Tokens defined by strings are added next by sorting them in order of decreasing regular expression length (longer expressions are added first).
我猜你正在使用函数,所以模式是按文件中出现的顺序排列的,因为你的第二个模式——更长——如果它们被定义为字符串,将首先应用.但是没有看到您的实际文件,很难确定。
无论如何,Ply lexers 的传统智慧是使用尽可能少的模式,更喜欢将关键字映射到带有字典的标记。在 GRBL 的情况下,一种可能是使用 [Gg][0-9]+(\.[0-9]÷)?
作为模式,然后在语义操作中提取索引。
你的模式 [Gg]{1}0* 是通用的,它匹配 G00 和 G01 https://regex101.com/r/gkz0Wb/1 在第二种情况下,您只剩下单个字符 1.
您必须使此模式更具体,例如通过在结束模式 [Gg]{1}0*\s 添加空白字符 https://regex101.com/r/dsSFaG/1