竞争正则表达式(竞争条件)

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 手册定义了顺序:

  1. All tokens defined by functions are added in the same order as they appear in the lexer file.
  2. 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