1

我正在为大学编译器学科实践编写一个小型编译器,当我尝试编译我的程序时它说:

In file included from lexer.l:2:
parser.y++:21: error: ISO C++ forbids declaration of ‘Expresion’ with no type
parser.y++:21: error: expected ‘;’ before ‘*’ token
make: *** [principal] Error 1

在这里,我给你来自 lexer.l 文件的第 2 行:

#include "parser.tab.h++"

和 parser.y++ 的第 21 行。

Expresion *exp;

注意:“parser.tab.h++”是使用野牛从“parser.y++”生成的。

我正在使用 Flex 和 Bison GNU 工具来生成词汇和语法分析器。这里我给你整个 lexer.l 文件

%{
#include "parser.tab.h++"
int lineaComentario;
extern bool errorFlag;
#define POSICION \
    yylloc.last_line = 1; \
%}
digito                  [0-9]
letra                   [a-zA-Z]
entero                  {digito}+


%x COMENTARIO_TIPO1 COMENTARIO_TIPO2

%%
[ \t]+                  ;
\n                  { yylloc.last_line++; } 
"//"(.*)[\n]                yylloc.last_line++;     /* Comentarios de una sola linea */
program                 return PROGRAM;  
var                 return VAR;
integer                 return INTEGER;
begin                   return BEGINN;
end                 return END;
if                  return IF;
then                    return THEN;
else                    return ELSE;
while                   return WHILE;
do                  return DO;
print                   return PRINT;
({letra}|_)({letra}|{digito}|_)*    {if (yyleng > 16){printf("***ERROR,\n    el identificador : %s en linea : %d excede 16 caracteres\n",yytext,yylloc.last_line);errorFlag=true;yytext[16]='\0';};yylval.cadena=strdup(yytext);return ID;}
{entero}                {yylval.numero=atoi(yytext);if ((yyleng!=1)&&((atoi(yytext)>32767)||(yytext[0]=='0'))){printf("***ERROR,\n    el entero : %s en linea : %d esta fuera de rango u empieza con cero  \n",yytext,yylloc.last_line);};errorFlag=true; return INTLITERAL;}
"("                 return LPAREN;      
")"                 return RPAREN;
";"                 return SEMICOLON;
","                 return COMMA;
":="                    return ASSIGNOP;
"+"                 return PLUSOP;
"*"                 return MULTOP;
"-"                 return MINUSOP;
"/"                 return DIVOP;
"."                 return POINT;
":"                 return TWO_POINTS;
\"[^"\n]*\"             {yylval.cadena=strdup(yytext);return STR;}
\"[^"\n]*$                  {printf("***ERROR,\n    cadena sin cerrar en linea : %d\n",yylloc.last_line);yylloc.last_line++;errorFlag=true;}                
"(*"                        {BEGIN(COMENTARIO_TIPO1);lineaComentario=yylloc.last_line;}
"{"                         {BEGIN(COMENTARIO_TIPO2);lineaComentario=yylloc.last_line;}
[^[:alnum:]();,:+*/.{}"_\n-]+       {printf("***ERROR,\n    la siguiente secuencia de simbolos : %s en la linea : %d no ha sido reconocida :\n",yytext,yylloc.last_line);errorFlag=true;}       /* Modo panico */


<COMENTARIO_TIPO1>{
[^*]*                       ;                                   /* Cualquier cosa que no es '*' */
"*"+[^)]                ;                               /* '*' no seguida de ')'  */    
"*"+")"                         BEGIN(0);                           /* con "*)" se acaba modo comentario tipo 1 */
                                                    /* En caso de llegar al fin de fichero */ 
<<EOF>>                         {printf("***ERROR,\n    comentario sin cerrar. linea : %d \n",yylloc.last_line);errorFlag=true;yyterminate();}   
}

<COMENTARIO_TIPO2>{
[^}]*                           ;                               /* Cualquier cosa que no es '}' */
"}"                         BEGIN(0);                       /* con '}' se acaba modo comentario tipo 2 */
<<EOF>>                         {printf("***ERROR,\n    comentario sin cerrar, linea : %d \n",lineaComentario);errorFlag=true;yyterminate();}
}   

%%

parser.y++ 文件

%{
#include <stdio.h>
#include "codigo.h"
#include"tablaSimbolos.h++"
#include <sstream>
extern bool errorFlag;
extern int yylex(void);
string intToSTR(int num);
void yyerror(char *error);
TablaSimbolos tabla;
int dir = 1;
int despl = 0;
%}

%locations

%union{
char *cadena;
int numero;
Expresion *exp;
}

%type <exp> expression term factor


%token PROGRAM LPAREN RPAREN SEMICOLON POINT VAR TWO_POINTS COMMA INTEGER ASSIGNOP IF THEN ELSE WHILE DO PRINT PLUSOP MINUSOP MULTOP DIVOP BEGINN END
%token <numero> INTLITERAL
%token <cadena> STR
%token <cadena> ID

%%


program : PROGRAM ID LPAREN RPAREN SEMICOLON declarations compound_statement POINT
          {}
;
declarations: declarations VAR identifier_list TWO_POINTS type SEMICOLON
              {}
    | 
;
identifier_list: ID {
            Simbolo *aux = tabla.buscaSimbolo($1);
            if(aux!=NULL){
                errorFlag = true; 
                printf("***ERROR, variable %s en linea : %d esta previamente declarada\n",$1,@1.last_line);
            }else{
                Simbolo *nuevo =new Simbolo($1,despl,true);
                despl+=4; 
                tabla.nuevoSimbolo(nuevo);
            }
            free($1);
        }
    | identifier_list COMMA ID{
                    Simbolo *aux = tabla.buscaSimbolo($3);
                    if(aux!=NULL){
                        errorFlag = true; 
                        printf("***ERROR, variable %s en linea : %d esta previamente declarada\n",$3,@1.last_line);
                    }else{
                        Simbolo *nuevo =new Simbolo($3,despl,true);
                        despl+=4; 
                        tabla.nuevoSimbolo(nuevo);
                    }
                    free($3);
                }
;
type : INTEGER 
       {}
;
compound_statement : BEGINN optional_statements END
                     {}
;
optional_statements : statement_list
                     {}
    | 

;
statement_list : statement
                 {}
    | statement_list SEMICOLON statement
    {}
;
statement : ID ASSIGNOP expression{
        Simbolo *aux = tabla.buscaSimbolo($1);
        if(aux==NULL){
            errorFlag = true;
            printf("***ERROR, la variable %s en linea : %d no ha sido declarada previamente \n",$1,@1.last_line);
        }
        free($1);
    } 

    | compound_statement
    {}
    | IF expression THEN statement ELSE statement
    {}
    | IF expression THEN statement
    {}
    | WHILE expression DO statement
    {}
    | PRINT print_list
    {}
;
print_list : print_item
             {}
    | print_list COMMA print_item
        {}
;
print_item : expression
             {}
    | STR{      
        Simbolo *aux = tabla.buscaSimbolo($1);
        if(aux==NULL){ // si existe y como es cadena dejar anterior
            Simbolo *nuevo =new Simbolo($1,dir,false);
            dir++;
            tabla.nuevoSimbolo(nuevo);      
        }
    }
;
expression : expression PLUSOP term
             {}
    | expression MINUSOP term
    {}
    | term
    {}
;
term : term MULTOP factor
       {}
    | term DIVOP factor
    {}
    | factor
    {$$ = $1}
;
factor : MINUSOP factor
         {
        $$ = new Expresion(""); // new Temp()
        $$->concatenar($2); 
        Cuadrupla *c = new Cuadrupla("SUB","0",$2->getResult(),$$->getResult());
        $$->concatenar(c)
    }
    | LPAREN expression RPAREN
    { $$ = $2; } // copia
    | ID{
        Simbolo *aux = tabla.buscaSimbolo($1);  
        if(aux==NULL) {
            errorFlag = true;
            printf("***ERROR, no se ha declarado la variable %s en linea : %d\n",$1,@1.last_line);
        }else
            $$ = new Expresion($1);
    }
    | INTLITERAL
    { $$ = new Expresion(intToSTR($1)); }
;

%%

string intToSTR(int num){
   stringstream ss;
   ss << num;
   return ss.str();
}

void yyerror(char *error) {
    printf("%s!\n",error);
}

表达式类在文件 "codigo.h" 中声明:

#include <string>
#include <list>

using namespace std;

class Cuadrupla{
    private: 
        string op;
        string arg1;
        string arg2;
        string res;
    public:
        Cuadrupla(string op, string arg1, string arg2, string res);
        void toString();
        string getResult();

};

class Expresion{
    private:
        list<Cuadrupla *> codigo;   
        string result;
    public:
        string getResult();
        Expresion(string result);
        void concatenar(Expresion *exp);
        void concatenar(Cuadrupla *cuad);
        void toString();
};

class Sentencia{
    private:
        list<Cuadrupla *> codigo;   

    public:
        Sentencia();
        void concatenar(Expresion *exp);
        void concatenar(Cuadrupla *cuad);
        void concatenar(Sentencia *sent);
        void toString();            
};

和我的makefile:

principal: principal.c++ tablaSimbolos.c++ parser.tab.c++ lex.yy.c 
    g++ -Wno-write-strings principal.c++ tablaSimbolos.c++ parser.tab.c++ lex.yy.c -lfl -o miniPascal
parser.tab.c++ parser.tab.h++: parser.y++
    bison -d parser.y++
lex.yy.c: lexer.l
    flex lexer.l
clear: 
    rm -f lex.yy.c parser.tab.c++ parser.tab.h++ miniPascal

我没有看到我以前在 JAVA 中编码的问题。

4

2 回答 2

1

看来,你需要一个;后定义的联合。

于 2012-07-17T19:51:00.780 回答
1

我发现如果我使用我创建的类,例如 MyClass 在野牛的语法定义文件中的 %union 定义中,然后我在另一个源文件(lexer.l在我的情况下)其中 Myclass 不是定义的类型。

有两种解决方案:

  • 在需要的文件中包含 MyClass.h,例如,如果我在 lexer.l 中包含grammar.tab.h,我必须在 lexer.l 中也包含 MyClass.h
  • 将 %code 指令与 requires 选项一起使用:

    %code 需要{ class MyClass; }

于 2012-07-18T02:22:26.760 回答