Wind-Son 发表于 2007-10-29 14:22

执行语义动作的问题

书上说语义动作可以在产生式右部的任何地方执行,比如这样的文法
1、E ==> TR
2、R ==> addop T {print1 (addop.lexeme)}R1
3、T ==> num{print(num.val)}
在上面第2个产生式的 print 的执行发生在 T 的规约结束后、R1 的规约开始前。
问题是这里在 T 规约后整个产生式还没有最终确定,怎么能确定使用 R ==> addop T {print1 (addop.lexeme)}R1 这个产生式对应的语义动作?
比如还有一个产生式
4、F ==> addop T {print2 (addop.lexeme)}R2
岂不是有二义性了?怎么区分到底执行print1还是print2?望达人指点

cjaizss 发表于 2007-10-29 15:00

你以上的文法中,(E,R,T,F)
当只遍历到addop T的时候,因为addop T的非唯一性是无法判断到底是R还是F的,执行动作(print1,print2)必须要发生在R/F分清楚之后

Wind-Son 发表于 2007-10-29 15:20

谢谢
那是说print1 的执行不可能发生在 T 的规约结束后、R1 的规约开始前,必须是
2、R ==> addop T {print1 (addop.lexeme)}R1
整个产生式形成后?

加入R1也有相关的语义动作
R1 ==> M{print3}
怎么保证print1在print3之前执行?

Wind-Son 发表于 2007-10-30 09:50

看到这样的解释:
用户有时希望把一个动作放在产生式的其它地方,而不是最右端。例如,在对条件语句Stmt→if Expr then {/*action1*/}Stmt{/*action2*/} 进行处理时,为了能够及时回填Expr的真出口,需在then后“嵌入”语义动作。一般说来,解决此类问题的方法,是对原文法进行语法变换。除此而外,YACC还提供了一种更简单的处理方法,即允许用户自由地在产生的右部的任何位置嵌入所希望的语义动作。但需指出,YACC将自动为其增加ε-产生式,以保证“动作”在进行“归约”时才被执行
这样的语法递归下降即可分析,不过yacc用的是自底向上LALF(1)

[ 本帖最后由 cjaizss 于 2007-10-30 13:19 编辑 ]

Wind-Son 发表于 2007-10-30 12:52

回复 #5 hotelcn2007 的帖子

???:em14:
页: [1]
查看完整版本: 执行语义动作的问题