我目前正在尝试创建一个可以接受和识别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,这就是目标。但是,我的理解显然是不正确的,因为我遇到语法错误,希望有人可以帮助我解决这种理解不足的问题。