Как исправить порядок, в котором разбирается простая команда оболочки? - PullRequest
0 голосов
/ 25 марта 2019

Используя правила грамматики, определенные ниже, я пытаюсь разобрать простую команду оболочки, скажем, как 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", $2);
            free($2);
        }
        ;

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

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

Аргументы в порядке, но команда заканчивается последней.Как мне получить их в правильном порядке?

Ответы [ 2 ]

0 голосов
/ 25 марта 2019

Bison создает парсеры снизу вверх , что означает, что если вы рассматриваете синтаксический анализ как дерево, то узлы обрабатываются раньше своих родителей.(Другими словами, это обход после заказа.)

Таким образом, действие для

 cmd_and_args:  WORD arg_list { … }

выполняется после действия для arg_list.

НадеюсьЯ не понимаю, почему это может быть проблемой, но вы можете изменить его, используя Midrule Action или используя единицу продукции для извлечения командного слова.

Midrule Action

cmd_and_args:  WORD { /* print $1*/ arg_list { /* arg_list is now $3 */ }

Производство единицы

cmd_and_args: command_word arg_list { … }

command_word: WORD { /* print $1 */ }

Примечание: грамматика не представляет реальную грамматику оболочки, которая позволяет присваиваниям предшествовать командному слову (например, LC_ALL=C sort file.txt).

0 голосов
/ 25 марта 2019

Я думаю, что решил это, вот обновленная грамматика:

%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", $1);
                  }
                  ;

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