Почему я получаю синтаксическую ошибку в Yacc, когда моя грамматика покрывает весь ввод? - PullRequest
0 голосов
/ 15 февраля 2019

В настоящее время я пытаюсь создать базовую грамматику, которая может принимать и распознавать команды оболочки.Тем не менее, я получаю синтаксические ошибки, которые избегают моего понимания.Я нарисовал дерево и, насколько я могу судить, покрываю все основания.Вот мой файл 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.Оттуда, command_and_args создается из command_word ls и arguments_list -al.Это создает pipe_list, который содержит только этот command_and_args.Оттуда создается command_line с этим новым pipe_list, пустым io_modifier_list, пустым background_optional и символом новой строки, когда я нажимаю enter.Это создает список команд, который является целью.Однако мое понимание, по-видимому, неверно, потому что я получаю синтаксическую ошибку, и я надеялся, что кто-то может помочь мне исправить это отсутствие понимания.

...