简体   繁体   中英

Bison/flex waits for input after recognizing a rule

I have the following files for lexical and syntactic analysis:

lexico.l

%{
    #include <iostream>
    #include <stdio.h>
    #include <string>   
    using namespace std;
    extern int yylex();
    #include "sintactico.h" // to get token types from Bison
%}
%option noyywrap
vfit1                       (?i:ff)
vfit2                       (?i:bf)
vfit3                       (?i:wf)
%%
#(.)*                       { printf("COMENTARIO\n"); }
[ \t\n]                     { /* Ignorar espacios en blanco */ }
[0-9]+                      { printf("INT\n"); yylval.sval = new string(yytext); return INT; }
\"([^\\\"]|\\.)*\"          { printf("STRING\n"); /*return STRING*/ }
(?i:mkdisk)                 { printf("MKDISK\n"); return MKDISK; }
(?i:size)                   { printf("SIZE\n");  yylval.sval = new string(yytext); return SIZE; }
(?i:unit)                   { printf("UNIT\n");  yylval.sval = new string(yytext); return UNIT; }
(?i:path)                   { printf("PATH\n");  yylval.sval = new string(yytext); return PATH; }
(?i:fit)                    { printf("FIT\n");  yylval.sval = new string(yytext); return FIT; }
-                           { printf("GUION\n"); return GUION; }
=                           { printf("IGUAL\n"); return IGUAL; }
{vfit1}|{vfit2}|{vfit3}     { printf("VFIT\n");  yylval.sval = new string(yytext); return VFIT; }
[bkmKBM]                    { printf("VUNIT\n"); yylval.sval = new string(yytext); return VUNIT; }
[a-zA-Z0-9/._]+             { printf("VSTRING\n"); yylval.sval = new string(yytext); return VSTRING; }
.                           { printf("ERROR\n"); }
%%

sintactico.y

%{  
    #include <cstdio>   
    #include <cstdlib>
    #include <string>
    #include <iostream>
    #include <map>
    using namespace std;
    map<string, string> opc;
    // Declare stuff from Flex that Bison needs to know about:
    extern int yylex();
    //extern int yyparse();
    extern FILE *yyin;
    #include "lexico.h"
    #include "cadena.h"

    void yyerror(const char *s);

    void test_map(){        
        cout << "opc.size() is " << opc.size() << endl;
        for(auto it : opc){
            cout << "*************************\n";
            cout << it.first << endl;
            cout << it.second << endl;
            cout << "*************************\n";
        }
    }       
%}

%union{
    int ival;       
    char cval;
    std::string *sval;  
}

%token        MKDISK RMDISK FDISK MOUNT UNMOUNT 
%token        TYPE DELETE 
%token        NAME ADD ID STRING GUION IGUAL

%token <sval> SIZE FIT PATH UNIT 
%token <sval> VSTRING INT VFIT VUNIT

%type <sval>  val_path

%%

axioma:             instr{
                        cout << "Finaliza" << endl;
                    };  

instr:              mkdisk{
                        analisis_mkdisk(opc);
                    };

mkdisk:             MKDISK list_mkdisk;

list_mkdisk:        list_mkdisk opc_mkdisk
                |   opc_mkdisk;

opc_mkdisk:         size
                |   fit
                |   unit
                |   path;

size:               GUION SIZE IGUAL INT{
                        cout << *$2 << ": " << *$4 << endl;
                        a_minus(*$2);                   
                        opc[*$2] = *$4;
                        delete $4;                      
                    };

fit:                GUION FIT IGUAL VFIT{
                        cout << *$2 << ": " << *$4 << endl;
                        a_minus(*$2); 
                        a_minus(*$4);
                        opc[*$2] = *$4; delete $4;
                    };

unit:               GUION UNIT IGUAL VUNIT{
                        cout << *$2 << ": " << *$4 << endl;
                        a_minus(*$2);
                        a_minus(*$4);
                        opc[*$2] = *$4; delete $4;
                    };

path:               GUION PATH IGUAL val_path{
                        cout << *$2 << ": " << *$4 << endl;
                        a_minus(*$2);
                        opc[*$2] = *$4; delete $4;
                    };

val_path:           VSTRING;                

%%

The following entry must be correct: mkdisk -size=20. The code for the size rule runs, however, in order for the code for the instr rule to run I have to press CTRL + D. Why does that happen? What is missing to add to the code? Is the parser lexical or syntactic?

EDIT: I removed the EOL token from the parser. What I don't really understand is, how does the parser know that the entry has finished? After entering the mkdisk -size = 20 command in the console, press the ENTER key. How do I tell Bison that my entry ends with ENTER? Why does the analyzer wait for an entry to finish the analysis?

It says here:

mkdisk:             MKDISK list_mkdisk EOL;

So mkdisk needs an EOL token in order to be complete, and it won't be reduced until it's complete.

But nowhere does your lexer return an EOL token. Assuming that EOL means "end of line", it would be logical for \n to produce an EOL token. But we have

[ \t\n]                     { /* Ignorar espacios en blanco */ }

So no EOL token, and no reduction. I don't see any way that the instr rule could run; if you enter an EOF, then the parser should report a syntax error from the missing EOL. But maybe I'm misunderstanding your error report.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM