如何修复简单 shell 命令的解析顺序?

How to fix the order in which a simple shell command is parsed?

使用下面定义的语法规则,我试图解析一个简单的 shell 命令,比如说 cd testFolder.

这些是我在 parser.y 中定义的规则:

%union{
    char *str;
}

%type <str> WORD

%%
command_list:/*empty*/
            |command_list command_line{  
                printf("myShell > ");
            }
            ;

arg_list:/*empty*/ 
        | arg_list WORD{
            printf("Args: %s\n", );
            free();
        }
        ;

cmd_and_args:
             WORD arg_list {
                printf("CMD: %s\n", );
                free();
             }
            ;

command_line:
            cmd_and_args NEWLINE {printf("NULL\n");
            }
            | NEWLINE {
                printf("NULL\n");
            }
%%

所以我想要的输出是:

CMD: cd
Args: testFolder
NULL

但我得到的是:

Args: testFolder
CMD: cd
NULL

对于像 vim -O test.c test1.c 这样的命令,我得到:

Args: -O
Args: test.c
Args: test1.c
CMD: vim
NULL

参数是按顺序排列的,但命令最终排在最后。如何以正确的顺序获取它们?

我想我解决了这个问题,这是更新后的语法:

%union{
    char *str;
}

%type <str> WORD
%%

command_list:/*empty*/
            |com

    mand_list command_line{  
                    printf("myShell > ");
                }
                ;

    command_line: simple_command NEWLINE{
                    printf("NULL\n");
                }
                | NEWLINE{
                    printf("NULL\n");
                }
                ;

    simple_command: simple_command words
                  | WORD{
                    printf("CMD: %s\n", );
                  }
                  ;

    words: WORD{
            printf("Args: %s\n", );
         }
    %%

Bison 生成自下而上 解析器,这意味着如果您将解析视为一棵树,节点将在其父节点之前被处理。 (换句话说,这是一个 post 阶遍历。)

因此

的行动
 cmd_and_args:  WORD arg_list { … }

arg_list 的操作之后执行。

我不明白为什么这会成为问题,但您可以通过使用 Midrule Action 或使用单位生产来提取命令词来更改它。

中期行动

cmd_and_args:  WORD { /* print */ arg_list { /* arg_list is now  */ }

单位产量

cmd_and_args: command_word arg_list { … }

command_word: WORD { /* print  */ }

注意:文法并不代表真正的 shell 文法,它允许赋值在命令词之前(例如 LC_ALL=C sort file.txt)。