Синтаксис и синтаксический анализ команд интерфейса человек-машина - PullRequest
2 голосов
/ 17 апреля 2010

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

Для этой цели я собираюсь построить утилиту cli. Утилита подключится к приложению и отправит пользовательские команды (однострочные строки) в приложение и будет ожидать ответа от приложения.

Команда должна содержать: - имя команды (например, display-session-table / set-log-level и т. д.) - необязательно, команда может иметь несколько аргументов (например, log-level = 10)

Вопрос, чтобы выбрать синтаксис и научиться разбирать его быстро и правильно.

Я не хочу изобретать велосипед, так что, возможно, уже есть ответ.

Ответы [ 5 ]

2 голосов
/ 17 апреля 2010

Посмотрите на пример интерпретатора ( пример использования ) из Boost.FunctionTypes . Обратите внимание, что он поддерживает только бесплатные функции.

1 голос
/ 17 апреля 2010

Библиотека Readline может быть полезна.

1 голос
/ 17 апреля 2010

boost :: program_options стоит посмотреть.

0 голосов
/ 17 апреля 2010

Я использую нечестивое сочетание readline, boost :: spirit и фабричного шаблона для обработки всего этого. Это было бы почти так же нечестиво, если бы не было непритязательного синтаксиса Си для чтения строк:)

Внешний цикл выглядит так

    while(true)
    {
            char *line(NULL);
            line = readline((cmd.leaf() + " > ").c_str());
            if (line && *line)
            {
                    add_history(line);
                    int error = ParseLine(line,*s_g, std::cout);
                    free(line);

                    if (error == ErrQuit)
                            break;
                    if (error == ErrSave)
                    ....

Каждая команда имеет функцию завершения и функцию синтаксического анализа / завершения

char **completeCreate(const std::vector<std::string> &, const char *text, int depth)
{
    switch (depth)
    {
            case 1:
            case 2:
            {
                    return  rl_completion_matches(text, rl_filename_completion_function);
                    break;
            }
            case 3:
            {
                    return rl_completion_matches(text, rulesFill);
                    break;
            }
    }
    return NULL;
}

Определяет завершитель для команды, которая принимает два аргумента, имя файла и строку, которая регистрируется с помощью механизма завершения readline через макрос factory +, который позволяет мне регистрировать все с помощью чего-то, похожего на это

REG_COMP (Создать, завершить создание);

На стороне парсера у меня аналогичная заводская настройка

int parseCreate(const std::vector<std::string> &names, Game &g, std::ostream &out)
{
    if (names.size() != 4)
            return parseHelpC(names, g, out);

    if (!CreateGame(names[1],names[2],names[3],g))
            return ErrGameCreation;

    return ErrNone;
}
REG_PARSE(Create,"CardList PowerList RuleSet");

, которая обеспечивает фактическую логику и текст справки

Я пропустил огромное количество кода, который склеивает все воедино, но был бы рад поделиться с вами отвратительностью, являющейся основой кода (в настоящее время это частный репозиторий git). Я с нетерпением жду, чтобы увидеть, есть ли у кого-то работающее лучше.

0 голосов
/ 17 апреля 2010

Я бы предложил использовать библиотеку JSON.

...