我有以下文件用于词法和句法分析:
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结尾?分析仪为什么要等待输入完成分析?
它在这里说:
mkdisk: MKDISK list_mkdisk EOL;
因此mkdisk
需要一个EOL
令牌才能完成,并且在完成之前不会减少它。
但是您的词法分析器无处返回EOL
令牌。假设EOL
表示“行尾”,则\n
产生EOL
令牌是合乎逻辑的。但是我们有
[ \t\n] { /* Ignorar espacios en blanco */ }
所以没有EOL令牌,也没有减少。我看不到instr
规则可以执行的任何方式;如果输入EOF,则解析器应从缺少的EOL中报告语法错误。但也许我误会了您的错误报告。