Bison / flex识别规则后等待输入

问题描述 投票:0回答:1

我有以下文件用于词法和句法分析:

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;                

%%

以下条目必须正确:mkdisk -size = 20。运行size规则的代码,但是,要运行instr规则的代码,我必须按CTRL +D。为什么会发生这种情况?缺少什么要添加到代码中?解析器是词法还是句法?

编辑:我从解析器中删除了EOL令牌。我真正不了解的是,解析器如何知道条目已完成?在控制台中输入mkdisk -size = 20命令后,按ENTER键。我如何告诉Bison我的输入以ENTER结尾?分析仪为什么要等待输入完成分析?

c++ parsing bison flex-lexer bisonc++
1个回答
1
投票

它在这里说:

mkdisk:             MKDISK list_mkdisk EOL;

因此mkdisk需要一个EOL令牌才能完成,并且在完成之前不会减少它。

但是您的词法分析器无处返回EOL令牌。假设EOL表示“行尾”,则\n产生EOL令牌是合乎逻辑的。但是我们有

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

所以没有EOL令牌,也没有减少。我看不到instr规则可以执行的任何方式;如果输入EOF,则解析器应从缺少的EOL中报告语法错误。但也许我误会了您的错误报告。

© www.soinside.com 2019 - 2024. All rights reserved.