开发者

Man machine interface command syntax and parsing

开发者 https://www.devze.com 2022-12-26 23:39 出处:网络
What I want is to add possibility to interact with开发者_运维问答 application, and be able to extract information from application or event ask it to change some states.

What I want is to add possibility to interact with开发者_运维问答 application, and be able to extract information from application or event ask it to change some states.

For that purpose I though of building cli utility. The utility will connect to the application and send user commands (one line strings) to the application and wait for response from the application.

The command should contain: - command name (e.g. display-session-table/set-log-level etc.) - optionally command may have several arguments (e.g. log-level=10)

The question to choose syntax and to learn parse it fast and correctly.

I don't want to reinvent the wheel, so maybe there's already an answer out there.


Take a look at the interpreter example (example usage) from Boost.FunctionTypes. Note however that as it is it only supports free functions.


boost::program_options is worth a look.


The Readline library could be useful.


I would suggest using a JSON library.


I use an unholy mix of readline, boost::spirit, and the factory pattern to handle all that. It wouldn't be nearly as unholy if it weren't for readlines unapologetic C syntax :)

The outer loop looks like this

    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)
                    ....

Each command has a completion function and a parser/completion function

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;
}

Defines the completer for a command that takes two arguments, a filename and a string, which gets registered with the completion mechanism of readline through a factory + macro, that lets me register everything with something that looks like this

REG_COMP(Create, completeCreate);

On the parser side, I have a similar factory setup

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");

that provides the actual logic and help text

I've left out huge swaths of code that glues everything together, but would be happy to share the hideousness that is the code base (it is currently a private git repository) I look forward to see if someone has something that works better.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号