2017-02-24 10 views
-1

나는 flex proyect를 컴파일하려하지만, 항상 동일한 오류가 발생하여 모든 것을 검색하고 토큰 <>을 사용하고 1 또는 0을 반환하거나 전화를 거는 것과 같은 대부분의 솔루션을 시도합니다. yywrap() ... 운이 없으면.플렉스/바이손 라인 25 : '에서 구문 오류. 파일의 마지막 줄

그리고 나는 어디에서 오류인지 알지 못합니다. 나는 교대/감소 충돌에 관한 84 가지 경고를 가지고 있지만 그게 문제가 될 수 있습니다.

은 tokens.l입니다 :

%option yylineno 

%{ 
#include <string> 
#include <iostream> 
#include <vector> 
using namespace std ; 
#include "parser.hpp" 

extern "C" int yywrap() { return(1); } 
#define TOKEN(t) processtoken(t, string(yytext, yyleng)) 

void processtoken (int t, string id) { 
    cout << t << " <" << id << ">" << endl ; 
} 

%} 

%option nounput 

%% 

programa        TOKEN(RPROGRAM); 
procedimiento       TOKEN(RPROC); 
variables        TOKEN(RVAR); 
si          TOKEN(RIF); 
entonces        TOKEN(RTHEN); 
repetir         TOKEN(RREPEAT); 
hasta         TOKEN(RUNTIL); 
siempre         TOKEN(RALWAYS); 
salir         TOKEN(RSALIR); 
leer         TOKEN(RREAD); 
escribir_linea       TOKEN(RWRITE); 
in          TOKEN(RIN); 
out          TOKEN(ROUT); 
entero         TOKEN(RENTERO); 
real         TOKEN(RREAL); 


[a-zA-Z](_?[a-zA-Z0-9])*    TOKEN(TID); 
\$[a-zA-Z](\-{0,1}[a-zA-Z0-9])*\-?  TOKEN(TID); 
\$[a-zA-Z](\_{0,2}[a-zA-Z0-9])*   TOKEN(TID); 
\(\*([^*]|\*+[^*)])*\*+\)    ; 

[ \t\n]         ; 
[0-9]+\.[0-9]*       TOKEN(TDOUBLE); 
[0-9]+         TOKEN(TINTEGER); 
[0-9]+\.[0-9]+([eE][-+]?[0-9]+)?  TOKEN(TREAL); 

"="          TOKEN(TASSIG); 
"=="         TOKEN(TEQUAL); 
">"          TOKEN(TCGT); 
">="         TOKEN(TCGE); 
"<"          TOKEN(TCLT); 
"<="         TOKEN(TCLE); 
"+"          TOKEN(TPLUS); 
"-"          TOKEN(TMINUS); 
"*"          TOKEN(TMUL); 
"/"          TOKEN(TDIV); 
"/="         TOKEN(TCNE); 
"("          TOKEN(TLPAREN); 
")"          TOKEN(TRPAREN); 
"{"          TOKEN(TLBRACE); 
"}"          TOKEN(TRBRACE); 
","          TOKEN(TCOMMA); 
":"          TOKEN(TCOLON); 
";"          TOKEN(TSEMIC); 

.          { cout << "Token desconocido: " << yytext << endl; yyterminate();} 

%% 

그리고 이것은 parser.y입니다 :

%{ 
    #include <stdio.h> 
    #include <iostream> 
    #include <vector> 
    #include <string> 
    using namespace std; 

    extern int yylex(); 
    extern int yylineno; 
    extern char *yytext; 
    string tab = "\t" ; 
    void yyerror (const char *msg) { 
    printf("line %d: %s at '%s'\n", yylineno, msg, yytext) ; 
    } 


%} 

%union { 
    string *str ; 
} 

%token <str> RPROGRAM RPROC RVAR RIF RTHEN RREPEAT RUNTIL 
%token <str> RALWAYS RSALIR RREAD RWRITE RENTERO RREAL 
%token <str> RIN ROUT 

%token <str> TID TDOUBLE TREAL TINTEGER 

%token <str> TASSIG TEQUAL TCGT TCGE TCLT TCLE TCNE 
%token <str> TPLUS TMINUS TMUL TDIV 
%token <str> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TCOLON TSEMIC 

%type <str> programa 
%type <str> declaraciones 
%type <str> lista_de_ident 
%type <str> resto_lista_id 
%type <str> tipo 
%type <str> decl_de_subprogs 
%type <str> decl_de_subprograma 
%type <str> argumentos 
%type <str> lista_de_param 
%type <str> clase_par 
%type <str> resto_lis_de_param 
%type <str> lista_de_sentencias 
%type <str> sentencia 
%type <str> variable 
%type <str> expresion 

%left TPLUS TMINUS TMUL TDIV 

%start programa 

%% 

programa : RPROGRAM TID 
     declaraciones 
     decl_de_subprogs 
     TLBRACE lista_de_sentencias TRBRACE 
     ; 


declaraciones : RVAR lista_de_ident TCOLON tipo TSEMIC declaraciones 
     | {} 
     ; 

lista_de_ident : TID resto_lista_id 
     ; 

resto_lista_id : TCOMMA TID resto_lista_id 
     | {} 
     ; 

tipo : RENTERO | RREAL 
     ; 

decl_de_subprogs : decl_de_subprograma decl_de_subprogs 
     | {} 
     ; 

decl_de_subprograma : RPROC TID argumentos declaraciones 
        TLBRACE lista_de_sentencias TRBRACE 
     ; 

argumentos : TLPAREN lista_de_param TRPAREN 
     | {} 
     ; 

lista_de_param : lista_de_ident TCOLON clase_par tipo resto_lis_de_param 
     ; 

clase_par : RIN | ROUT | RIN ROUT 
     ; 

resto_lis_de_param : TSEMIC lista_de_ident TCOLON clase_par tipo resto_lis_de_param 
     | {} 
     ; 

lista_de_sentencias : sentencia lista_de_sentencias 
     | {} 
     ; 

sentencia : variable TASSIG expresion TSEMIC 
     | RIF expresion RTHEN TLBRACE lista_de_sentencias TRBRACE 
     | RREPEAT TLBRACE lista_de_sentencias TRBRACE RUNTIL expresion TSEMIC 
     | RREPEAT RALWAYS TLBRACE lista_de_sentencias TRBRACE 
     | RSALIR RIF expresion 
     | RREAD TLPAREN variable TRPAREN TSEMIC 
     | RWRITE TLPAREN expresion TRPAREN TSEMIC 
     ; 

variable : TID 
     ; 

expresion : expresion TEQUAL expresion 
     | expresion TCGT expresion 
     | expresion TCLT expresion 
     | expresion TCGE expresion 
     | expresion TCLE expresion 
     | expresion TCNE expresion 
     | expresion TPLUS expresion 
     | expresion TMINUS expresion 
     | expresion TMUL expresion 
     | expresion TDIV expresion 
     | TID 
     | TINTEGER 
     | TREAL 
     | TLPAREN expresion TRPAREN 
     ; 

그리고 모든 시도를 사용하여 테스트 프로그램 임 다음 토큰은 토큰입니다.

programa ejemplo 
    variables a,b,c : entero; 
    variables d,e : real; 
(* esto es un comentario *) 

procedimiento sumar (x,y: in entero; resul: in out entero) 
    variables aux:entero; 
    { 
     repetir { 
      aux=x; 
      resul=y; 
      aux = aux - 1; 
      resul = resul+1; 
     } hasta aux /= 0; 
    } 

{ 
    leer(a); leer(b); 
    d= 1/b; 
    e= 1/a; 
    sumar(a,b,c); (* los que hagan llamadas a procedimientos *) 
    c= c*(c*d)+e; 
    escribir_linea(c*c); 
} 

항상 줄 마지막 줄에 오류가 있습니다. 줄 25 : ''에서 구문 오류가 발생했는데, 그 이유는 무엇입니까? 공백 토큰을 가지고 있기 때문에 EOF의 토큰이 작동하지 않아서 시도했습니다. < < EOF >> {yywrap();}하지만 끝나지 않습니다.

답변

1

스캐너 정의에 아무 것도 토큰을 파서로 반환하지 않습니다. 파서가 볼 수있는 유일한 토큰은 EOF를 볼 때 flex에 의해 자동으로 반환되는 END 토큰입니다.

그러나 문법은 빈 입력을 허용하지 않습니다. 입력의 첫 번째 토큰이 programa (예를 들어)이라고 주장합니다. 자연스럽게 EOF를 볼 때 구문 오류가보고됩니다.

EOF가 감지되면 토큰 텍스트가 없으므로 yytext은 유효하지 않습니다. (심지어 NULL이 될 수도 있으므로 사용해서는 안됩니다.) 전체적으로 보면 렉서 액션 바깥에 yytext을 사용하는 것은 좋은 생각이 아니며 yyerror에서이 코드를 사용하면 정의되지 않은 행동이 발생합니다. 들소 예제에서 때때로 그것을 볼 것입니다.)

+0

나는 그것을 얻지 못한다. 당신은 내가 EOF의 토큰을 명시해야한다고 말했습니까? 나는 그것을 시도했다 << EOF >> {yywrap();}하지만 막히게된다. yyerror 함수없이 시도했지만 오류를 표시하지 않지만 여전히 있습니다. – set92

+1

@ set92 아니요. rici는 렉서가 화면에 인쇄하는 대신 렉서가 리턴 토큰 (EOF 제외)을 만들어야한다고 말합니다. – sepp2k

+0

#define TOKEN (t) yylval.str = new std :: string (yytext, yyleng)에 대해 #define TOKEN (t)을 변경했습니다. 그리고 다른 문제는 함수 호출을위한 문법을 ​​가지고 있지 않았기 때문에 sumar (a, b, c)가있는 테스트 프로그램에서 삭제하고 이제는 모두 정상적으로 작동합니다. 모든 도움을 주셔서 감사합니다 – set92