Python/YACC词法分析器:什么是Token优先级?

12

我正在尝试在我的语法中使用保留字:

reserved = {
   'if' : 'IF',
   'then' : 'THEN',
   'else' : 'ELSE',
   'while' : 'WHILE',
}

tokens = [
 'DEPT_CODE',
 'COURSE_NUMBER',
 'OR_CONJ',
 'ID',
] + list(reserved.values())

t_DEPT_CODE = r'[A-Z]{2,}'
t_COURSE_NUMBER  = r'[0-9]{4}'
t_OR_CONJ = r'or'

t_ignore = ' \t'

def t_ID(t):
 r'[a-zA-Z_][a-zA-Z_0-9]*'
 if t.value in reserved.values():
  t.type = reserved[t.value]
  return t
 return None

然而,t_ID规则不知何故吞噬了DEPT_CODE和OR_CONJ。我该如何解决这个问题?我希望这两个词比保留字具有更高的优先级。
2个回答

16

问题得到解决!

今天我自己遇到了这个问题,并寻找解决方法 - 没有在 S/O 上找到答案 - 但在手册中找到了:http://www.dabeaz.com/ply/ply.html#ply_nn6

在构建主要正则表达式时,规则按以下顺序添加:

  • 通过函数定义的所有标记以与它们在词法分析器文件中出现的相同顺序添加。
  • 由字符串定义的标记随后按正则表达式长度递减的顺序排序(较长的表达式先添加)。

这就是为什么t_ID“击败”字符串定义。一个微不足道的(尽管残忍的)修复方法将是在def t_ID之前简单地添加 def t_DEPT_CODE(token): r'[A-Z]{2,}'; return token


0

有两件事需要注意:

  • 显然,“or”是一个保留字,就像“if”,“then”等一样。
  • 你的t_ID的正则表达式匹配了DEPT_CODE匹配的字符串的超集。

因此,我会这样解决:将“or”作为保留字包含进去,在t_ID中检查字符串的长度是否为2以及是否仅由大写字母组成。如果是这种情况,则返回DEPT_CODE。


不,这不是PLY的工作方式!匹配是按定义顺序进行的,因此理论上它应该选择t_DEPT_CODE到t_ID。绝对不是用手动检查t_ID来覆盖词法分析器的方法,请相信我。 - Nas Banov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接