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



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

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("COMENTARIOn"); }
[ tn]                     { /* Ignorar espacios en blanco */ }
[0-9]+                      { printf("INTn"); yylval.sval = new string(yytext); return INT; }
"([^\"]|\.)*"          { printf("STRINGn"); /*return STRING*/ }
(?i:mkdisk)                 { printf("MKDISKn"); return MKDISK; }
(?i:size)                   { printf("SIZEn");  yylval.sval = new string(yytext); return SIZE; }
(?i:unit)                   { printf("UNITn");  yylval.sval = new string(yytext); return UNIT; }
(?i:path)                   { printf("PATHn");  yylval.sval = new string(yytext); return PATH; }
(?i:fit)                    { printf("FITn");  yylval.sval = new string(yytext); return FIT; }
-                           { printf("GUIONn"); return GUION; }
=                           { printf("IGUALn"); return IGUAL; }
{vfit1}|{vfit2}|{vfit3}     { printf("VFITn");  yylval.sval = new string(yytext); return VFIT; }
[bkmKBM]                    { printf("VUNITn"); yylval.sval = new string(yytext); return VUNIT; }
[a-zA-Z0-9/._]+             { printf("VSTRINGn"); yylval.sval = new string(yytext); return VSTRING; }
.                           { printf("ERRORn"); }
%%

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。大小规则的代码运行,但是,为了使 instr 规则的代码运行,我必须按 CTRL + D。为什么会这样?缺少什么可以添加到代码中?解析器是词法还是句法?

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

它在这里说:

mkdisk:             MKDISK list_mkdisk EOL;

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

但是您的词法分析器不会返回EOL令牌。假设EOL的意思是"行尾",那么n生成一个EOL令牌是合乎逻辑的。但我们有

[ tn]                     { /* Ignorar espacios en blanco */ }

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

最新更新