flex / bison:'$'操作数提供大量/错误的文本块

时间:2015-09-03 09:49:26

标签: bison yacc

我不知道如何把这个,因为“寻址”似乎是指“%”操作数和行/列的规范,这不是我想要的。我想弄清楚“$”符号究竟是如何工作的。另外我不知道这些是操作数还是它们是什么,如果你能告诉我,请做,如果没有,请避免专注于我称之为的东西,并强调告诉我“$”的作用。 我在野牛中有这么长的表达:

for: KW_FOR S_PARENTHESIS_OPEN assignment S_SEMICOLON gen_ex S_SEMICOLON assignment S_PARENTHESIS_CLOSE command_block 
{
printf("condition: %s", $3);
};

(请注意,大写字母中的任何内容都是直接对应于单词/符号的标记) 输入是:

void myProgram ()
BEGIN
x = 1;
if( x < 3 ) x = 2;

if(x > 3) x = 3; else x = 2;

while (x < 2)
BEGIN
y = 2;
END

for ( x = 1; y < 3; z = 2)
BEGIN
z = 4;
END

END

如果我要求for,我希望printf()会给我$1关键字,但它实际上是从前一个“while”循环中的y = 2开始的,我无法弄清楚,因为它超出了表达的范围。

那么,这究竟是怎么决定我所做的参考在哪里?既然我们就在这里,那么这又叫什么呢?

编辑:我知道我写了3美元,而且有效。如果我写1美元它不会按预期工作。我问的是这些东西叫做什么,以及野牛如何决定什么是第一个符号,以及如果我要求$ 1,它为什么它会从特定表达式之前给出我的东西。这就是我想知道的,以及如何正确地引用这些东西。

1 个答案:

答案 0 :(得分:1)

$n指的是当前产品右侧的 n th 符号的语义值

终端的语义值是由返回终端代码的扫描器规则分配给yylval的任何内容。如果flex动作没有为yylval分配任何内容,则没有语义值(或者更准确地说,语义值未初始化,并且未定义行为引用它)。< / p>

非终端的语义值是解析器(bison)操作分配给$$的任何内容。如果没有与生产关联的操作,或者操作未向$$分配任何内容,则从$1(在该生产中)复制非终端的语义值。在这种情况下,如果$1没有语义值,那么相应的非终端和未定义的行为都不会尝试使用该值。

语义值的(C)类型为YYSTYPE,默认为int,您可以在序言中设置。或者你可以将它定义为联合类型 - 也就是普通的C union - 在这种情况下,野牛需要知道哪个联盟成员适用于每个终端和非终端。在这种情况下,扫描程序需要分配给yylval的正确成员。

我强烈建议您阅读bison manual。您可以跳到semantics上的部分,但如果您刚刚开始,您会发现从一开始就阅读它非常有用,并特别注意这些示例。

祝你好运。

快速建议:不要用S_PARENTHESIS_OPEN之类的东西填写你的语法。这无助于提高可读性或效率。更好的风格是将单引号字符用于单字符标记,并为更长的标记定义双引号别名:

 /* It is not necessary to declare single-quoted character tokens */
%token KW_FOR "for"
%%
 /* Example: */
for: "for" '(' assignment ';' gen_ex ';'  assignment ')' command_block

在扫描仪中,返回单字符标记的实际字符;较长的令牌需要使用%token行中声明的符号名称:

"for"     { return KW_FOR; }
[();]     { return yytext[0]; }

上面的第二个弹性规则列出了可能的单字符标记,但在弹性规则结束时使用后备规则更容易:

.          { return yytext[0]; }

因为任何与bison规范中的单引号不对应的字符都会在解析器中触发语法错误。