在 yacc 规则中注入新的词素

Inject new lexemes in a yacc Rule

我有以下语法(这是一个简化的语法):

S -> EXPR

EXPR -> ITEM addop EXPR
EXPR -> ITEM

ITEM -> num
ITEM -> ident

拥有:

num: a floating point number
ident: a string representing an identifier
addop: +

我正在为 python 使用 PLY 库,并且有以下代码:

def p_L_S(self,p):
  ''' S : EXPR'''
  p[0] = p[1]

def p_L_EXPR_1(self,p):
  ''' EXPR : ITEM addop EXPR'''
  p[0] = p[1] + p[2]

def p_L_EXPR_2(self,p):
  ''' EXPR : ITEM'''
  p[0] = p[1]

def p_L_ITEM_1(self,p):
  ''' ITEM : num '''
  p[0] = float(p[1])

def p_L_ITEM_2(self,p):
  ''' ITEM : ident '''
  p[0] = value_of_expr_associated_to_ident(p[1])

[...]

在最后一个函数 (p_L_ITEM_2) 中,我想解释与 p[1] 关联的字符串(这是语法可识别的表达式)而不启动另一个解析。 今天,函数 value_of_expr_associated_to_ident 启动了与 ident 关联的表达式的新解析(调用 parse 方法)。 但这给出了非常糟糕的性能,即使它有效。

有没有办法将与 ident 关联的表达式关联的词法发送到解析器,以避免必须开始新的解析?

不知道说清楚了没有,再说清楚。

非常感谢。 山姆

如果您正在尝试使用函数式语言进行某种惰性求值,请继续阅读。这并不像看起来那么简单,而且我只提供了关于该方法的粗略想法。

如果与标识符关联的值是表示语言表达式的纯字符串,那么您需要执行递归调用解析。

但似乎至少缓存生成的解析树是值得的(这意味着您的解析器需要创建一个解析树,而不是立即进行评估)。或者,您可以在将字符串值分配给变量时将其解析为解析树。

无论您如何完成递归解析,您都需要以某种方式处理无限递归,例如 r 的值为 r(或 r + 1)。