Yacc:无法解析

时间:2019-12-09 07:49:19

标签: c compiler-construction yacc lex

我遇到无法解决的问题。我有两个文件lexer.l和parser.y(用于令牌和语法+三个地址代码)。我正在使用以下命令在Linux上编译文件:

yacc -d parser.y
lex lexer.l

这给了我lex.yy.c和y.tab.c和y.tab.h文件。

但是,当我尝试将它们一起编译为示例文件时,我试图为其构建(input.txt)的语言,例如:

gcc y.tab.c lex.yy.c -lfl -o example

我收到以下警告:

parser.y:963:6: warning: conflicting types for ‘yyerror’
 void yyerror(const char *s) {
      ^~~~~~~
y.tab.c:2333:7: note: previous implicit declaration of ‘yyerror’ was here
       yyerror (YY_("syntax error"));
       ^~~~~~~

当我尝试执行“示例”目标文件时,出现错误:

{EEK, parse error!  Message: syntax error

它表明程序被卡在parser.y(在底部)中创建的yyerror函数中。我不确定为什么它会在y.tab.c文件中弄乱。我想要做的就是成功执行示例(input.txt)的“示例”对象文件。但是我猜程序似乎陷入了yyerror中。我也是使用lex和yacc的新手。有办法摆脱这个错误吗?任何帮助将不胜感激。谢谢。

lexer.l

/*Lex File*/
%{
#include <stdio.h>
#include <string.h>

#include "y.tab.h"

char c;


%}

DIGIT  [0-9]+
NUMBER [+-]?[0-9]+|[+-]?[0-9]*"."[0-9]+
STRING \"(\\.|[^\"])*\"
BOOLEAN ["True" "False"]
ID [a-zA-Z_][0-9a-zA-Z_]*
FLOAT [0-9]+[.][0-9]*

ARITHMETIC_OPERATORS ['+' '-' '*' '/']
OTHER_CHARACTERS ['=' '.' '(' ')' '{' '}' '[' ']']
TYPES ["Number" "String" "Boolean" "Return"]

%%
[ \t] ;
[\n] ;


"If"    { return (IF); }
"Else"  { return (ELSE); }
"While" { return (WHILE); }
"Main()" {return (MAIN); }
"Read()" {return (READ);}
"Class"  {return (CLASS);}

"Number" {return (TYPES);}
"String" {return (TYPES);}
"Boolean" {return (TYPES);}
"Print"   {return (PRINT);}
"Return"  {return (TYPES);}


"<!--".*"--!>" ;


">" {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"<" {yylval.sval = strdup(yytext);
        return (REL_OPT);}
">="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"<="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"!="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}
"=="    {yylval.sval = strdup(yytext);
        return (REL_OPT);}

"|" {yylval.sval = strdup(yytext);
        return (OR);}
"&" {yylval.sval = strdup(yytext);
        return (AND);}
"!" {yylval.sval = strdup(yytext);
        return (NOT);}

{NUMBER}  { yylval.nval = atof(yytext);
       return NUMBER; }

{BOOLEAN}  { yylval.sval = yytext;
       return BOOLEAN; }

{STRING}  { yylval.sval = yytext;
       return STRING; }

{ID} {
        yylval.sval = strdup(yytext);
        return ID; 
}
{ARITHMETIC_OPERATORS}   {
                c = yytext[0];
                 return(c);
              }

{OTHER_CHARACTERS}   {
                 c = yytext[0];
                 return(c);
              }

%%

parser.y

/*Yacc File with semantics*/

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
char *s1, *s2;
char *b1, *b2;

struct exprType{

    char *addr;
    char *code;
};


int n=1;
int nl = 1;
char *var;
char num_to_concatinate[10];
char num_to_concatinate_l[10];
char *ret;
char *temp;

char *label;
char *label2;
char *check;

char *begin;

struct exprType *to_return_expr;

char * newTemp(){

    char *newTemp = (char *)malloc(20);
    strcpy(newTemp,"t");
    snprintf(num_to_concatinate, 10,"%d",n);
    strcat(newTemp,num_to_concatinate);

    n++;
    return newTemp;
}

char * newLabel(){

    char *newLabel = (char *)malloc(20);
    strcpy(newLabel,"L");
    snprintf(num_to_concatinate_l, 10,"%d",nl);
    strcat(newLabel,num_to_concatinate_l);

    nl++;
    return newLabel;
}
%}

%start startSym

%union {
    float nval;
    char *sval;
    struct exprType *EXPRTYPE;
}


%token <nval> NUMBER
%token <sval> BOOLEAN
%token <sval> STRING
%token <sval> READ
%token <sval> PRINT
%token <sval> ID IF ELSE WHILE TYPES REL_OPT OR AND NOT MAIN CLASS TRUE FALSE
%token <sval> '+' '-' '*' '/' '\n' '=' '.'
%type <sval> list text construct block dec bool program startSym
%type <EXPRTYPE> expr stat


%left OR
%left AND
%left NOT
%left REL_OPT
%right '='
%left '+' '-'
%left '*' '/' '%'


%%

startSym:   program 
            {
                s1 = $1;

                label = newLabel();
                check = strstr(s1, "NEXT");

                while(check != NULL) {
                    strncpy(check, label, strlen(label));
                    strncpy(check + strlen(label),"    ", (4 - strlen(label)));
                    check = strstr(s1, "NEXT");
                }

                ret = (char*) malloc(strlen(s1) + 10);
                ret[0] = 0;

                strcat(ret, s1);
                strcat(ret, "\n");
                strcat(ret, label);
                strcat(ret, "3AD ends here\n");

                printf("\nIntermediate code:\n");
                puts(ret);

                $$ = ret;
            }

        ;

program :   program construct 
        {  
            s1 = $1;
            s2 = $2;

            label = newLabel();

            check = strstr(s1, "NEXT");

            while(check != NULL) {
                strncpy(check, label, strlen(label));
                strncpy(check + strlen(label), "    ", (4 - strlen(label)));
                check = strstr(s1, "NEXT");
            }

            ret = (char*) malloc(strlen($1) + strlen($2) + 4);
            ret[0] = 0;
            strcat(ret, $1);
            strcat(ret, "\n");
            strcat(ret, label);
            strcat(ret, " : ");
            strcat(ret, $2);

            printf("Program construct\n");


            puts(ret);
            $$ = ret;

        }
        |
        construct
            {
            printf("Final construct \n");
            puts($1);
            $$ = $1;
            }
        |
        list
            {
            printf("Final list \n");
            puts($1);
            $$ = $1;
            }
        ;

construct :     block
        {
            $$ = $1;
        }
        |
        WHILE '(' bool ')' block
        {
            printf("Inside WHILE\n");
            puts($5);
            b1 = $3;
            s1 = $5;

            begin = newLabel();
            label = newLabel();

            check = strstr(b1, "TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,"NEXT",4);
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            check = strstr (s1,"NEXT");

            while(check!=NULL){
                strncpy (check,begin,strlen(begin));
                strncpy (check+strlen(begin),"    ",(4-strlen(begin)));
                check = strstr (s1,"NEXT");
                }

            ret = (char *)malloc(strlen(b1)+strlen(s1)+20);
            ret[0] = 0;
            strcat(ret,begin);
            strcat(ret," : ");
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,s1);

            strcat(ret,"\n");
            strcat(ret,"goto ");
            strcat(ret,begin);

            printf("Final return from WHILE\n");
            puts(ret);

            $$ = ret;
        }


        |
        IF '(' bool ')' block
        {
            printf("Inside IF\n");

            label = newLabel();
            b1 = $3;

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,"NEXT",4);
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            ret = (char *)malloc(strlen(b1)+strlen($5)+4);
            ret[0] = 0;
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,$5);

            puts(ret);
            $$ = ret;

        }

        |
        IF '(' bool ')' block ELSE block
        {
            printf("Inside IF then ELSE\n");

            b1 = $3;
            label = newLabel();

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
            }

            label2 = newLabel();
            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label2,strlen(label2));
                strncpy (check+strlen(label2),"    ",(4-strlen(label2)));
                check = strstr (b1,"FAIL");
            }

            ret = (char *)malloc(strlen(b1)+strlen($5)+strlen($7)+20);
            ret[0] = 0;
            strcat(ret,b1);
            strcat(ret,"\n");
            strcat(ret,label);
            strcat(ret," : ");
            strcat(ret,$5);
            strcat(ret,"\n");
            strcat(ret,"goto NEXT");
            strcat(ret,"\n");
            strcat(ret,label2);
            strcat(ret," : ");
            strcat(ret,$7);

            puts(ret);

            $$ = ret;



        }

        | 
        CLASS ID block
        {



               $$ = $3;

        }
        ;

block:  '{' list '}'
        {
                printf("Inside class block\n");
                $$ = $2;
        }

        |

        '{' construct '}'
        {
                $$ = $2;
        }
        |

        '[' list ']'
        {
                printf("Inside specific block\n");
                $$ = $2;
        }

        |
        '[' construct ']'
        {
                $$ = $2;
        }

        ;


list:    stat               
        {
            $$ = $1->code;
        }
        |

        list stat
        {
            ret = (char*) malloc(strlen($1) + strlen($2->code) + 4);
            ret[0] = 0;

            strcat(ret, $1);
            strcat(ret, "\n");
            strcat(ret, $2->code);

            printf("Inside list stat \n");
            puts(ret);
            $$ = ret;
        }

       |
        list error '\n'
        {
            yyerrok;
        }

        |
        MAIN block
        {


            $$ = $2;

        }
        ;


stat:    '.'
        {


          to_return_expr = (struct exprType*) malloc(sizeof(struct exprType));

          to_return_expr->addr = (char *) malloc(20);
          to_return_expr->addr = $1;

          to_return_expr->code = (char*) malloc(2);
          to_return_expr->code[0] = 0;

          $$ = to_return_expr; 
        }

        |
        expr '.'
        {
            $$ = $1;

        } 
        |

        dec '.'
        {
         to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;   
        }
        |

        text '=' expr '.'
        {
            printf("Assignment statement \n");

            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
            to_return_expr->addr = (char *)malloc(20);
            to_return_expr->addr = newTemp();

            ret = (char*)malloc(20);
            ret[0] = 0;

            strcat(ret, $1);
            strcat(ret, "=");
            strcat(ret, $3->addr);
            printf("RET = \n");
            puts(ret);

            temp = (char*) malloc(strlen($3->code) + strlen(ret) + 6);

            temp[0] = 0;

            if($3->code[0] != 0) {
                strcat(temp, $3->code);
                strcat(temp, "\n");
            }
            strcat(temp, ret);
            printf("TEMP = \n");

            puts(temp);

            to_return_expr->code = temp;

            $$ = to_return_expr;
        }

        |

        dec '=' expr '.'
        {

        printf("Dec and Assignment statement \n");
        to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,$1);
        strcat(ret,"=");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
        }


        ;

dec :   TYPES text 
        {   
            $$ = $2;
        }
        ;

bool :  expr REL_OPT expr
        {
            printf("Inside rel opt\n");

            temp = (char *)malloc(strlen($1->code)+strlen($3->code)+50);
            temp[0] = 0;

            if($1->code[0]!=0){
                strcat(temp,$1->code);
                strcat(temp,"\n");
                }
            if($3->code[0]!=0){
                strcat(temp,$3->code);
                strcat(temp,"\n");
                }

            ret = (char *)malloc(50);
            ret[0] = 0;
            strcat(ret,"if(");
            strcat(ret,$1->addr);
            strcat(ret,$2);
            strcat(ret,$3->addr);
            strcat(ret,") goto TRUE \n goto FAIL");

            strcat(temp,ret);

            $$ = temp;
        }

        |
        bool OR bool
        {
            printf("Inside OR\n");
            b1 = $1;
            b2 = $3;

            label = newLabel();

            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            temp = (char *)malloc(strlen(b1)+strlen(b2)+10);
            temp[0] = 0;

            strcat(temp,b1);
            strcat(temp,"\n");
            strcat(temp,label);
            strcat(temp," : ");
            strcat(temp,b2);

            $$ = temp;
        }

        |
        bool AND bool
        {
            printf("Inside AND\n");

            b1 = $1;
            b2 = $3;

            label = newLabel();

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            temp = (char *)malloc(strlen(b1)+strlen(b2)+10);
            temp[0] = 0;

            strcat(temp,b1);
            strcat(temp,"\n");
            strcat(temp,label);
            strcat(temp," : ");
            strcat(temp,b2);

            $$ = temp;
        }

        |
        NOT '(' bool ')'
        {
            printf("Inside NOT\n");
            b1 = $3;
            label = "TEFS";

            check = strstr (b1,"TRUE");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TRUE");
                }

            label = "TRUE";
            check = strstr (b1,"FAIL");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"FAIL");
                }

            label = "FAIL";
            check = strstr (b1,"TEFS");

            while(check!=NULL){
                strncpy (check,label,strlen(label));
                //strncpy (check+strlen(label),"    ",(4-strlen(label)));
                check = strstr (b1,"TEFS");
                }
            $$ = b1;
        }

        |
        '(' bool ')'
        {
            $$ = $2;
        }




        ;

expr:    '(' expr ')'
         {
           $$ = $2;
         }

         |

         expr '*' expr
         {

           printf("Multiplication : ");

           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"*");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

        $$ = to_return_expr;


         }

         |
         expr '/' expr
          {

           printf("Division: ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"/");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

        $$ = to_return_expr;
        }

         |
         expr '+' expr
         {


           printf("Addition : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Addition : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"+");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
         }

         |

         expr '-' expr
        {


           printf("Subtraction : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Subtraction : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = newTemp();

        ret = (char *)malloc(20);
        ret[0] = 0;

        strcat(ret,to_return_expr->addr);

        strcat(ret,"=");
        strcat(ret,$1->addr);
        strcat(ret,"-");
        strcat(ret,$3->addr);
        printf("RET  = \n");
        puts(ret);

        temp = (char *)malloc(strlen($1->code)+strlen($3->code)+strlen(ret)+6);

        temp[0] = 0;

        if ($1->code[0]!=0){
            strcat(temp,$1->code);
            strcat(temp,"\n");
            }
        if ($3->code[0]!=0){
            strcat(temp,$3->code);
            strcat(temp,"\n");
            }
        strcat(temp,ret);
        printf("TEMP = \n");

        puts(temp);

        to_return_expr->code = temp;

            $$ = to_return_expr;
        }

        |
        text
        {


           printf("Text : ");
           to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

            printf("Text : ");
            to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));

        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;
        }

        |
        BOOLEAN
        {


          // printf("Inside BOOLEAN : %s\n",$1);

            printf("Inside BOOLEAN : %s\n",$1);
        //$$ = $1;

        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;
        }

        |

        STRING
        {


           /*printf("Inside String : ");
          printf("Inside STRING : %s\n",$1);
        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;*/


            printf("Inside STRING : %s\n",$1);
        var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;
        //$$ = $1;



        }

        |

        NUMBER
        {





            printf("Inside NUMBER : %f\n",$1);
        //$$ = $1;

        var = (char *)malloc(20);
            snprintf(var, 10,"%f",$1);

        $$ = var;
        }

        |
        READ
        {

                /*printf("Inside Read: \n");
                to_return_expr = (struct exprType *)malloc(sizeof(struct exprType));
        to_return_expr->addr = (char *)malloc(20);
        to_return_expr->addr = $1;

        to_return_expr->code = (char *)malloc(2);
        to_return_expr->code[0] = 0;

        $$ = to_return_expr;*/

                printf("Inside Read: \n");
                var = (char *)malloc(20);
            snprintf(var, 10,"%s",$1);
        $$ = var;

        }
        ;

text:   ID
        {


           printf("Inside Identifier : ");



           $$ = $1;
        }

        ;


%%

extern int yylex();
extern int yyparse();
extern FILE *yyin;

main() {
    // open a file handle to a particular file:
    FILE *myfile = fopen("input.txt", "r");
    // make sure it is valid:
    if (!myfile) {
        printf("I can't open a.snazzle.file!");
        return -1;
    }
    // set lex to read from it instead of defaulting to STDIN:
    yyin = myfile;

    // parse through the input until there is no more:
    do {
        yyparse();
    } while (!feof(yyin));

}

void yyerror(const char *s) {
    printf("EEK, parse error!  Message: ");
    puts(s);
    //printf("\n");
    // might as well halt now:
    exit(-1);
}

input.txt

Class ABC {

    Main() [

        Number a = 8.

        Return 0.

    ]
}

1 个答案:

答案 0 :(得分:0)

问题很简单,您在使用yyerror()函数之前没有声明它。因此,隐式声明返回int,而您的函数定义为返回void,这会导致冲突类型错误。

解决方案是,在文件顶部(即此处)声明yyerror()函数:

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
char *s1, *s2;
char *b1, *b2;
void yyerror(const char *s);

那应该可以解决此错误。

要调试解析错误,可以使用yacc选项调用-t并声明变量

int yydebug = 1;

位于文件顶部。然后,解析器将为每个读取的令牌输出状态信息。在这种情况下,问题在于您的词法分析器规则不正确,尤其是正则表达式:

BOOLEAN ["True" "False"]
ARITHMETIC_OPERATORS [+*/-]
OTHER_CHARACTERS [=.(){}\[\]]
TYPES ["Number" "String" "Boolean" "Return"]

应该是

 BOOLEAN (True|False)
 ARITHMETIC_OPERATORS [+*/-]
 OTHER_CHARACTERS [=.()\{\}\[\]]
 TYPES (Number|String|Boolean|Return)

flex定义文件有几个可用的示例,它们可能使您了解正则表达式的外观。