当我的语法似乎覆盖所有输入时,为什么在Yacc中出现语法错误?

时间:2019-02-15 03:07:45

标签: syntax grammar yacc lex

我目前正在尝试创建一个可以接受和识别shell命令的基本语法。但是,我遇到了语法错误,使我无法理解。我画了一棵树,据我所知,我遮盖了所有基地。这是我的lex文件

%{

#include <cstring>
#include "y.tab.hh"

static  void yyunput (int c,char *buf_ptr  );

void myunputc(int c) {
  unput(c);
}

%}

%option noyywrap

%%

  return PIPE;
}

"<" {
  return LESS;
}

"&" {
  return AMP;
}

\n {
  return NEWLINE;
}

[ \t] {
  /* Discard spaces and tabs */
}

">" {
  return GREAT;
}

"2>" {
  return TGREAT;
}

">&" {
  return GREATAMP;
}

">>" {
  return DUBGREAT;
}

">>&" {
  return DUBGREATAMP;
}



[^ \t\n][^ \t\n]*  {
  /* Assume that file names have only alpha chars */
  yylval.cpp_string = new std::string(yytext);
  return WORD;
}

这是我的yacc文件

%code requires 
{
#include <string>

#if __cplusplus > 199711L
#define register      // Deprecated in C++11 so remove the keyword
#endif
}

%union
{
  char        *string_val;
  // Example of using a c++ type in yacc
  std::string *cpp_string;
}

%token <cpp_string> WORD
%token NOTOKEN GREAT NEWLINE PIPE LESS AMP TGREAT GREATAMP DUBGREAT DUBGREATAMP

%{
//#define yylex yylex
#include <cstdio>
#include "shell.hh"

void yyerror(const char * s);
int yylex();

%}

%%

goal:
  command_list
  ;

command_list:
  command_line
  | command_list command_line
  ;

command_line:
  pipe_list io_modifier_list background_optional NEWLINE
  | NEWLINE
  | error NEWLINE{yyerrok;}
  ;

pipe_list:
  pipe_list PIPE command_and_args
  | command_and_args
  ;

command_and_args:
  command_word argument_list {
    Shell::_currentCommand.
    insertSimpleCommand( Command::_currentSimpleCommand );
  }
  ;

argument_list:
  argument_list argument
  | /* can be empty */
  ;


io_modifier_list:
  io_modifier_list iomodifier_opt
  | /*empty*/
  ;


iomodifier_opt:
  GREAT WORD {
    printf("   Yacc: insert output \"%s\"\n", $2->c_str());
    Shell::_currentCommand._outFile = $2;
  }
  | DUBGREAT WORD {
    printf("   Yacc: insert output \"%s\"\n", $2->c_str());
    Shell::_currentCommand._outFile = $2;
  }
  | DUBGREATAMP WORD {
    printf("   Yacc: insert output \"%s\"\n", $2->c_str());
    Shell::_currentCommand._outFile = $2;
    Shell::_currentCommand._background = true;
  }
  | GREATAMP WORD {
    printf("   Yacc: insert output \"%s\"\n", $2->c_str());
    Shell::_currentCommand._outFile = $2;
    Shell::_currentCommand._background = true;
  }
  | LESS WORD {
    printf("   Yacc: insert input \"%s\"\n", $2->c_str());
    Shell::_currentCommand._inFile = $2;
  }
  | /* can be empty */ 
  ;

background_optional:
  AMP {
    Shell::_currentCommand._background = true;
  }
  | /*empty*/
  ;

argument:
  WORD {
    printf("   Yacc: insert argument \"%s\"\n", $1->c_str());
    Command::_currentSimpleCommand->insertArgument( $1 );
  }
  ;

command_word:
  WORD {
    printf("   Yacc: insert command \"%s\"\n", $1->c_str());
    Command::_currentSimpleCommand = new SimpleCommand();
    Command::_currentSimpleCommand->insertArgument( $1 );
  }
  ;

%%

void
yyerror(const char * s)
{
  fprintf(stderr,"%s", s);
}

#if 0
main()
{
  yyparse();
}
#endif

在最简单的用例中,我尝试了ls -al。以我的理解,ls被识别为command_word。然后-al被识别为参数。这将创建一个仅包含-al的新arguments_list。从那里,从command_word ls和argument_list -al创建command_and_args。这将创建一个仅包含此command_and_args的pipe_list。从那里,使用此新的pipe_list,一个空的io_modifier_list,一个空的background_optional和当我按Enter时的换行符创建一个命令行。这将创建一个command_list,这就是目标。但是,我的理解显然是不正确的,因为我遇到语法错误,希望有人可以帮助我解决这种理解不足的问题。

0 个答案:

没有答案