在 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
)。
我有以下语法(这是一个简化的语法):
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
)。