问题 Python / YACC Lexer:令牌优先级?


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

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。我怎么能绕过这个?我希望那两个人比保留的词更优先。


11644
2018-05-26 05:45


起源



答案:


谜团已揭开!

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

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

  • 函数定义的所有标记的添加顺序与它们在lexer文件中的显示顺序相同。
  • 接下来通过按正则表达式长度递减的顺序对字符串定义的标记进行排序(较长的表达式为   先添加)。

这就是t_ID“击败”字符串定义的原因。一个微不足道(虽然残酷)的解决方案将是 只是 def t_DEPT_CODE(token): r'[A-Z]{2,}'; return token 之前 def t_ID


15
2018-05-02 23:04





我想到两件事:

  • 显然,'或'是一个保留字,如'if','then'等。
  • 您对t_ID的RE匹配DEPT_CODE匹配的字符串的超集。

因此,我将按如下方式解决:包括'或'作为保留字,在t_ID中,检查字符串的长度是否为2,以及它是否仅由大写字母组成。如果是这种情况,请返回DEPT_CODE。


0
2018-05-26 08:09



不,这不是PLY的工作原理!匹配是按照定义的顺序完成的,所以理论上它应该将t_DEPT_CODE提取到t_ID。 无疑 不是用t_ID手动检查来覆盖词法分析器的方法,相信我 - Nas Banov


答案:


谜团已揭开!

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

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

  • 函数定义的所有标记的添加顺序与它们在lexer文件中的显示顺序相同。
  • 接下来通过按正则表达式长度递减的顺序对字符串定义的标记进行排序(较长的表达式为   先添加)。

这就是t_ID“击败”字符串定义的原因。一个微不足道(虽然残酷)的解决方案将是 只是 def t_DEPT_CODE(token): r'[A-Z]{2,}'; return token 之前 def t_ID


15
2018-05-02 23:04





我想到两件事:

  • 显然,'或'是一个保留字,如'if','then'等。
  • 您对t_ID的RE匹配DEPT_CODE匹配的字符串的超集。

因此,我将按如下方式解决:包括'或'作为保留字,在t_ID中,检查字符串的长度是否为2,以及它是否仅由大写字母组成。如果是这种情况,请返回DEPT_CODE。


0
2018-05-26 08:09



不,这不是PLY的工作原理!匹配是按照定义的顺序完成的,所以理论上它应该将t_DEPT_CODE提取到t_ID。 无疑 不是用t_ID手动检查来覆盖词法分析器的方法,相信我 - Nas Banov