我在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;
任何想法我做错了什么?
答案 0 :(得分:1)
可能是因为语法必须提前查看一个令牌,以决定按照您显示的规则进行缩减。
当规则减少时执行操作,并且通常在语法知道它可以/应该减少先前规则之前必须再读取一个令牌。
例如,如果一个表达式可以由一个不确定的添加术语序列组成,那么它必须超出最后一个术语,才能知道没有另一个'+'来继续表达。
在看到Yacc / Bison语法和Lex / Flex分析器之后,一些问题变得明显,而其他问题则需要更多的整理。
$$
中传播合适值所需的语法,以确保规则具有必要的信息。关键词大部分都不需要值;像变量名和数字这样的东西。返回的原型解决方案存在重大内存泄漏,因为它大量使用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