嵌套while循环的Yacc解析器

时间:2014-05-07 07:55:45

标签: parsing compiler-construction yacc

我试图使用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不考虑变量赋值

1 个答案:

答案 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_newlinesopt_newlines中的statement_list,因此您可以获得转换/缩小冲突}。只需删除多余的opt_newlines即可轻松解决此类冲突。