在Bison规则中printf的麻烦

时间:2010-08-21 23:16:23

标签: action printf bison flex-lexer

我在Bison文件中尝试了类似的东西......

ReturnS: RETURN expression {printf(";")}

...但是分号在下一个标记之后打印,超过此规则,而不是在表达式之后。这个规则是因为我们需要将输入文件转换为类似c的形式,并且原始语言在return语句中的表达式之后不需要分号,但C确实如此,所以我想我会添加它用printf手动输出到输出。这似乎不起作用,因为分号被添加但由于某种原因,它在解析下一个标记之后(在ReturnS规则之外)而不是当表达式规则返回到ReturnS时被添加。

此规则也会导致相同的结果:

loop_for: FOR var_name COLONEQUALS expression TO {printf("%s<=", $<chartype>2);} expression STEP {printf("%s+=", $<chartype>2);} expression {printf(")\n");} Code ENDFOR

除了前两个printf无法正常工作(我将发布另一个关于此的问题),最后的printf实际上是在解析了“Code”规则的第一个标记/文字之后调用的,结果是这样的:

for (i=0; i<=5; i+=1
a)
=a+1;

而不是

for (i=0; i<=5; i+=1)
a=a+1;

任何想法我做错了什么?

2 个答案:

答案 0 :(得分:1)

可能是因为语法必须提前查看一个令牌,以决定按照您显示的规则进行缩减。

当规则减少时执行操作,并且通常在语法知道它可以/应该减少先前规则之前必须再读取一个令牌。

例如,如果一个表达式可以由一个不确定的添加术语序列组成,那么它必须超出最后一个术语,才能知道没有另一个'+'来继续表达。


在看到Yacc / Bison语法和Lex / Flex分析器之后,一些问题变得明显,而其他问题则需要更多的整理。

  • 使用词法分析器进行大量打印意味着语法不能正确控制出现的内容。分析仪做得太多了。
  • 分析器也没有做足够的工作 - 使语法处理字符串和数字一次成为一个字符是可能的,但不必要的努力工作。
  • 如果需要保留评论,则处理评论很棘手。在常规的C编译器中,词法分析器会抛出注释;在这种情况下,必须保留评论。处理它的规则从语法(它导致shift / reduce和减少/减少冲突,因为匹配注释的空字符串)移动到词法分析器。这可能并不总是最佳的,但在这种情况下似乎工作正常。
  • 词法分析器需要确保在需要值时为yylval返回合适的值。
  • $$中传播合适值所需的语法,以确保规则具有必要的信息。关键词大部分都不需要值;像变量名和数字这样的东西。
  • 语法必须在适当的地方进行打印。

返回的原型解决方案存在重大内存泄漏,因为它大量使用strdup()并且根本没有使用free()。确保泄漏是固定的 - 可能通过使用char数组而不是YYSTYPE的char指针 - 留给OP。

答案 1 :(得分:0)

评论不是提供代码示例的好地方,所以我将提供一个代码示例,在Jonathan(上面回复)对我的代码做了一些工作之后。所有应有的信誉归他所有,这不是我的。

Jonathan建议FLEX不打印任何东西,只返回BISON,然后应该自行处理所有打印。

所以,而不是像这样......


FLEX

"FOR"   {printf("for ("); return FOR;}
"TO"    {printf("; "); return TO;}
"STEP"  {printf("; "); return STEP;}
"ENDFOR"    {printf("\n"); printf("}\n"); return ENDFOR;}
[a-zA-Z]+   {printf("%s",yytext); yylval.strV = yytext; return CHARACTERS;}
":="    {printf("="); lisnew=0; return COLONEQUALS;}

BISON

loop_for:   FOR var_name {strcpy(myvar, $<strV>2);} COLONEQUALS expression TO {printf("%s<=", myvar);} expression STEP {printf("%s+=", myvar);} expression {printf(")\n");} Code ENDFOR

......他建议:


FLEX

[a-zA-Z][a-zA-Z0-9]*    { yylval = strdup(yytext); return VARNAME;}
[1-9][0-9]*|0           { yylval = strdup(yytext); return NUMBER; }

BISON

loop_for:   FOR var_name COLONEQUALS NUMBER TO NUMBER STEP NUMBER
    { printf("for (%s = %s; %s <= %s; %s += %s)\n", $2, $4, $2, $6, $2, $8); }
var_name:   VARNAME