为什么yacc或bison将$1转换为yyvsp[(1)-(1)].s?
Yacc来源如下:为什么yacc或bison将$1转换为yyvsp[(1)-(1)].s?,c,bison,yacc,C,Bison,Yacc,Yacc来源如下: element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL); if ($$ == NULL) { ADD_MISSING_ELEMENT (graph, $1); SET_ERROR (graph->error, GST
element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL);
if ($$ == NULL) {
ADD_MISSING_ELEMENT (graph, $1);
SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
/* if FATAL_ERRORS flag is set, we don't have to worry about backwards
* compatibility and can continue parsing and check for other missing
* elements */
if ((graph->flags & GST_PARSE_FLAG_FATAL_ERRORS) == 0) {
gst_parse_strfree ($1);
YYERROR;
}
}
gst_parse_strfree ($1);
}
| element ASSIGNMENT { gst_parse_element_set ($2, $1, graph);
$$ = $1;
它被翻译成如下代码:
{ (yyval.e) = gst_element_factory_make ((yyvsp[(1) - (1)].s), NULL);
if ((yyval.e) == NULL) {
ADD_MISSING_ELEMENT (graph, (yyvsp[(1) - (1)].s));
SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), (yyvsp[(1) - (1)].s));
/* if FATAL_ERRORS flag is set, we don't have to worry about backwards
* compatibility and can continue parsing and check for other missing
* elements */
if ((graph->flags & GST_PARSE_FLAG_FATAL_ERRORS) == 0) {
gst_parse_strfree ((yyvsp[(1) - (1)].s));
YYERROR;
}
}
gst_parse_strfree ((yyvsp[(1) - (1)].s));
}
break;
其中一种翻译转换为:
gst_element_factory_make ($1, NULL)
致:
[(1)-(1)]
把我弄糊涂了。
为什么
[(1)-(1)]
句子代表了$1
的价值?正如乔纳森·莱夫勒(Jonathan Leffler)在一篇评论中所说,bison和yacc以一种便于代码生成的风格生成正确的代码,而不是针对人类读者
然而,各种堆栈的处理相当简单。Bison维护两个或三个堆栈:状态堆栈;值堆栈;以及可选的位置堆栈。这三个堆栈是独立的,因为否则就需要创建一个包含状态、值和(如有必要)位置的堆栈插槽结构
堆栈的大小始终相同,这意味着在值堆栈(以及位置堆栈)的开头有一个未使用的插槽。如果你参考LR解析算法的经典描述,比如在《龙之书》的“LR解析算法”一节——《我的版本》第4.7节——你会清楚地看到这一点;堆栈的状态比语法符号多一个,因此没有X0
:
在这种情况下,值堆栈的顶部将精确地
V1 V2 … Vm
V1 V2…Vm
(其中Vi
是符号Xi
的语义值)。或者,用野牛的话来说:
$1$2…$m
这意味着,
$1
是yyvsp[1-m]
,$2
是yyvsp[2-m]
,依此类推,在yyvsp[m-m]
处的$m
。这正是bison生成的代码所做的;它将$i
表示为yyvsp[(i)-(m)]
,其中m
是右手边被缩短的长度(以语法符号表示)。yyvsp
是指向数组的一部分的指针,该数组包含(指向)与$1
,$2
相对应的值,等。$1
的值存储在yyvsp[0]
中,可以将其写入yyvsp[(1)-(1)]
,其中第一个1
是$1
的后缀,第二个是文本1。这是机器生成的代码,您不需要阅读它。如果你这样做,你必须接受它是(1)正确的,(2)方便程序生成而不是程序员阅读。而.s
部分是因为你有一个联合类型,$1
(标识符
)的类型使得值存储在联合的s
元素中。
s0 X1 s1 X2 s2 … Xm sm
A → X1 X2 … Xm
V1 V2 … Vm