我正在开发一个控制台应用程序。为了创建一个解释器,我使用了 Flex 和 Bison。我创建了一个语法,但每次尝试使用字符串时都会收到“语法错误”而没有任何其他解释。我正在尝试使用的字符串是: MKDISK -PATH=./home/erick/disk.dk -u=k -size=1000\n
我知道生产有问题
comando : MKDISK lista_param
{
printf("Mkdisk con parametros\n");
Mkdisk m;
m.agregarParametros($2);
m.assignParameters();
}
;
因为我注意到,如果我添加一个没有 lista_param 的产品,只是 MKDISK,它可以工作,并且解析器将始终执行该产品,如果字符串与另一个字符串匹配。
解析器.yy:
%skeleton "lalr1.cc" /* -*- C++ -*- */
%defines
%define api.parser.class {Parser}
%define api.token.constructor
%define api.value.type variant
%define parse.trace
%define parse.error verbose
%param { Driver& driver }
%code requires
{
class Driver;
class Comando;
class Parametro;
class Mkdisk;
}
%{
using namespace std;
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include "driver.h"
%}
/******* TERMINALES ********/
%token <std::string> NUM"NUM" SIZE"SIZE" F"F" PATH"PATH" U"U" BF"BF" FF"FF" WF"WF" K"K" M"M" RUTA"RUTA" MKDISK"MKDISK" RMDISK"RMDISK"
%token GUION"GUION" IGUAL"IGUAL"
/******* NO TERMINALES ********/
%start inicio;
%type <Parametro> parametro
%type <Comando> comando
%type <std::vector<Parametro>> lista_param
%type <std::string> atributo nom_param
%%
inicio : lista_comandos "\n"
{
printf("Primer nivel del arbol\n");
}
;
lista_comandos : lista_comandos comando
{
printf("Lista de comandos\n");
}
| comando
{
printf("Comando individual\n");
}
;
comando : MKDISK lista_param
{
printf("Mkdisk con parametros\n");
Mkdisk m;
m.agregarParametros($2);
m.assignParameters();
}
;
lista_param : lista_param parametro
{
printf("Lista de parametros\n");
$$=$1;
$$.push_back($2);
}
| parametro
{
printf("parametro individual\n");
vector<Parametro> params;
params.push_back($1);
$$ = params;
}
;
parametro : GUION nom_param IGUAL atributo
{
printf("Quinto nivel del arbol\n");
Parametro param;
param.setNombre($2);
param.setValor($4);
$$ = param;
}
;
nom_param : SIZE { $$=$1; }
| F { $$=$1; }
| PATH { $$=$1; }
| U { $$=$1; }
;
atributo : NUM { $$=$1; }
| BF { $$=$1; }
| FF { $$=$1; }
| WF { $$=$1; }
| K { $$=$1; }
| M { $$=$1; }
| RUTA { $$=$1; }
;
%%
void yy::Parser::error( const std::string& error){
std::cout <<"\e[0;31m"<< error << std::endl;
}
词法分析器
%{
#include <stdio.h>
#include <string>
#include "driver.h"
#include "parser.tab.hh"
%}
%option case-insensitive
%option noyywrap
%option outfile="scanner.cc"
DIGIT [0-9]
NUM {DIGIT}+("."{DIGIT}+)?
PATH \"?(\/([^\/\n])*)+\"?
%%
"MKDISK" { return yy::Parser::make_MKDISK(yytext); }
"RMDISK" { return yy::Parser::make_RMDISK(yytext); }
"SIZE" { return yy::Parser::make_SIZE(yytext); }
"F" { return yy::Parser::make_F(yytext); }
"PATH" { return yy::Parser::make_PATH(yytext); }
"U" { return yy::Parser::make_U(yytext); }
{NUM} { return yy::Parser::make_NUM(yytext);}
"BF" { return yy::Parser::make_BF(yytext); }
"FF" { return yy::Parser::make_FF(yytext); }
"WF" { return yy::Parser::make_WF(yytext); }
"K" { return yy::Parser::make_K(yytext); }
"M" { return yy::Parser::make_M(yytext); }
{PATH} { return yy::Parser::make_RUTA(yytext); }
"-" { return yy::Parser::symbol_type(); }
"=" { return yy::Parser::symbol_type(); }
[[:blank:]] {}
. { printf("Caracter no reconocido: %s\n",yytext);}
%%
void Driver::runScanner(){
yy_flex_debug = false;
yyin = fopen (file.c_str (), "r");
if(yyin == NULL){
printf("No se encontro el archivo de entrada");
exit(1);
}
}
void Driver::runScannerWithText(std::string text){
yy_flex_debug = true;
YY_BUFFER_STATE buffer = yy_scan_string(text.c_str());
}
void Driver::closeFile(){
fclose(yyin);
}