我试图使用yacc和lex编写一个解析器来计算嵌套循环的数量(while或for)。我开始实现while while循环。但由于某种原因,解析器在最后给出了一个错误闭幕式。
这是代码。
%{
#include<stdio.h>
/*parser for counting while loops*/
extern int yyerror(char* error);
int while_count=0;
extern int yylex();
%}
%token NUMBER
%token VAR
%token WHILE
%%
statement_list : statement'\n'
| statement_list statement'\n'
;
statement :
while_stmt '\n''{' statement_list '}'
| VAR '=' NUMBER ';'
;
while_stmt :
WHILE '('condition')' {while_count++;}
;
condition :
VAR cond_op VAR
;
cond_op : '>'
| '<'
| '=''='
| '!''='
;
%%
int main(void){
yyparse();
printf("while count:%d\n",while_count);
}
int yyerror(char *s){
printf("Error:%s\n",s);
return 1;
}
该代码有什么问题。在yacc中是否有提及可选参数的方法?像之后的“\ n”?
这是词法分析器代码
%{
#include"y.tab.h"
/*lexer for scanning nested while loops*/
%}
%%
[\t ] ; /*ignore white spaces*/
"while" {return WHILE;}
[a-zA-Z]+ {return VAR;}
[0-9]+ {return NUMBER;}
'$' {return 0;}
'\n' {return '\n' ;}
. {return yytext[0];}
%%
VAR是一个变量名,只有ascii字符,WHILE是关键字while.type不考虑变量赋值
答案 0 :(得分:1)
你似乎遇到的问题是空循环体,而不是嵌套循环。如上所述,您的语法在while循环体中至少需要一个语句。您可以通过允许空语句列表来解决此问题:
statement_list: /* empty */
| statement_list statement '\n'
;
您还可以询问是否可以选择换行。最简单的方法是让词法分析器简单地丢弃换行符(作为空格)而不是返回它们。然后只需删除语法中的换行符,换行符就会出现在任意两个令牌之间,并且会被忽略。
如果您出于某种原因确实必须在语法中添加换行符,则可以添加如下规则:
opt_newlines: /* empty */ | opt_newlines '\n' ;
然后在您想要允许换行的任何地方使用此规则(替换语法中的所有文字'\n'
。)但是,必须注意不要冗余地使用它。如果您执行以下操作:
statement_list: /* empty */
| statement_list statement opt_newlines
;
while_stmt opt_newlines '{' opt_newlines statement_list opt_newlines '}'
由于循环中}
之前的换行符可能是while中的opt_newlines
或opt_newlines
中的statement_list
,因此您可以获得转换/缩小冲突}。只需删除多余的opt_newlines
即可轻松解决此类冲突。