我有以下文件用于词法和句法分析:
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 的语法错误。但也许我误解了您的错误报告。