编写自己的Shell解释器-4[转]

根据这个思路,我们来看对应的 lex 规则。

%%

"\""            {BEGIN QUOTE;}

<QUOTE>[^\n"]+  {add_arg(yytext);}

<QUOTE>"\""     {BEGIN 0;}

<QUOTE>\n       {BEGIN 0; do_list_cmd(); reset_args();}

";"             {add_simple_arg(yytext);}

">"             {add_simple_arg(yytext);}

"<"             {add_simple_arg(yytext);}

"|"             {add_simple_arg(yytext);}

[^ \t\n|<>;"]+  {add_arg(yytext);}

\n              {do_list_cmd(); reset_args();}

.               ;

%%

我们对这些规则逐条解释:

144条规则,目的是为了在命令行中支持引号,它们用到了 lex 规则的状态特性。

1"\""            {BEGIN QUOTE;}

2<QUOTE>[^\n"]+  {add_arg(yytext);}

3<QUOTE>"\""     {BEGIN 0;}

4<QUOTE>\n       {BEGIN 0; do_list_cmd(); reset_args();}

1、  如果扫描到引号(),那么进入 QUOTE 状态。在这个状态下,即使扫描到空白字符或“;”、“>”、“<”、“|”,也要当作普通的字符。

2、  如果处于 QUOTE状态,扫描到除引号和回车以外的字符,那么调用 add_arg()函数,把整个字符串加入到参数数组中。

3、  如果处于QUOTE状态,扫描到引号,那么表示匹配了前面的引号,于是恢复到默认状态。

4、  如果处于QUOTE状态,扫描到回车,那么结束了本次扫描,恢复到默认状态,并执行 do_list_cmd(),来执行对列表命令的处理。

以下几条规则,是在处于默认状态的情况下的处理。

5";"              {add_simple_arg(yytext);}

6">"              {add_simple_arg(yytext);}

7"<"              {add_simple_arg(yytext);}

8"|"               {add_simple_arg(yytext);}

9[^ \t\n|<>;"]+      {add_arg(yytext);}

10\n               {do_list_cmd(); reset_args();}

5、  如果遇到分号(;),因为这是一个列表命令结束的操作符,所以作为一个单独的参数,执行 add_simple_arg(),将它加入参数数组。

6、  如果遇到 >,因为这是一个简单命令结束的操作符,所以作为一个单独的参数,执行 add_simple_arg(),将它加入参数数组。

7、  如果遇到 <,因为这是一个简单命令结束的操作符,所以作为一个单独的参数,执行 add_simple_arg(),将它加入参数数组。

8、  如果遇到管道符号(|),因为这是一个管道命令结束的操作符,所以作为一个单独的参数,执行 add_simple_arg(),将它加入参数数组。

9、  对于不是制表符(tab)、换行符(’\n’)、| <>和分号(;)以外的字符序列,作为一个普通的参数,加入参数数组。

10、              如果遇到换行符,那么结束本次扫描,执行 do_list_cmd(),来执行对列表命令的处理。

11、              对于任意其它字符,忽略

通过 lex 的“规则”把用户输入的命令行分解成一个个的参数之后,都要执行 do_list_cmd() 来执行对列表命令的处理。

posted @ 2008-12-05 22:31  aoogur  阅读(308)  评论(0编辑  收藏  举报