如何用PLY处理一个token的多条规则

0 投票
1 回答
954 浏览
提问于 2025-04-18 00:01

我正在处理一个jison文件,并使用Python的PLY库中的lex模块将其转换为解析器生成器。

我注意到,在这个jison文件中,某些标记(tokens)有多个规则。例如,对于标记CONTENT,文件中指定了以下三个规则:

[^\x00]*?/("{{")                 {
                                   if(yytext.slice(-2) === "\\\\") {
                                     strip(0,1);
                                     this.begin("mu");
                                   } else if(yytext.slice(-1) === "\\") {
                                     strip(0,1);
                                     this.begin("emu");
                                   } else {
                                     this.begin("mu");
                                   }
                                   if(yytext) return 'CONTENT';
                                 }

[^\x00]+                         return 'CONTENT';

// marks CONTENT up to the next mustache or escaped mustache
<emu>[^\x00]{2,}?/("{{"|"\\{{"|"\\\\{{"|<<EOF>>) {
                                   this.popState();
                                   return 'CONTENT';
                                 }

在另一个情况下,COMMENT标记也有多个规则:

<com>[\s\S]*?"--}}"              strip(0,4); this.popState(); return 'COMMENT';
<mu>"{{!--"                      this.popState(); this.begin('com');
<mu>"{{!"[\s\S]*?"}}"            strip(3,5); this.popState(); return 'COMMENT';

当这些规则适用于不同的状态时,区分起来似乎很简单,但如果它们适用于相同的状态呢?

我该如何使用ply.lex将这个jison转换为Python规则呢?

编辑

如果有帮助的话,这个jison文件是handlbars.js源代码的一部分。可以查看:https://github.com/wycats/handlebars.js/blob/master/src/handlebars.l

1 个回答

0

这个问题比较复杂,实际上它包含了两个问题。

Jison(这是手柄解析器使用的语言,不是bison)有一些其他词法分析器没有的特性,特别是PLY就没有。这使得将你展示的Jison词法代码转换为PLY变得困难。不过,这并不是你关注的问题。我们可以回答你的基本问题,如何在PLY中让多个正则表达式返回一个单一的标记,但这并不能解决你选择的示例代码的问题!

首先,我们来解决你问的问题。在PLY中,使用@TOKEN装饰器可以实现多个正则表达式返回一个标记,具体可以参考PLY手册(第4.11节)。

例如,我们可以这样做:

comment1 = r'[^\x00]*?/("{{")'
comment2 = r'[^\x00]+'
comment = r'(' + comment1 + r'|' + comment2 + r')'

@TOKEN(comment)
def t_COMMENT(t)
 ....

然而,这对于你从Jison得到的规则并不适用,因为它们使用了Jison的新特性,叫做起始条件(可以查看Jison手册)。在这里,this.begin这个短语用来引入一个状态名称,然后可以在其他模式中使用。这就是<mu><emu><com>的来源。PLY中没有这样的特性。

为了匹配这些词素,实际上需要回到手柄/胡子语言的语法,创建新的正则表达式。我觉得在这里完全为你重新实现整个手柄语言可能有点过于复杂。

不过,我已经为你找到了一个解决方案的步骤,适合任何走这条路的人。

撰写回答