Как маркировать специальные символы в зависимости от пробелов (<> | и т. Д.) - PullRequest
0 голосов
/ 29 января 2019

Я обнаружил, что проект, выполненный несколько лет назад, нашел здесь , который выполняет простой анализ командной строки.Хотя мне действительно нравится его функциональность, он не поддерживает синтаксический анализ специальных символов, таких как <,>, & и т. Д. Я пошел дальше и попытался добавить некоторые функции для конкретного анализа этих символов, добавив некоторые из тех же условий, что и в существующем коде.используется для поиска пробелов, экранирующих символов и кавычек:

bool _isQuote(char c) {
    if (c == '\"')
            return true;
    else if (c == '\'')
            return true;

    return false;
}

bool _isEscape(char c) {
    if (c == '\\')
        return true;

    return false;
}

bool _isWhitespace(char c) {
    if (c == ' ')
        return true;
    else if(c == '\t')
        return true;

    return false;
}
.
.
.

Что я добавил:

bool _isLeftCarrot(char c) {
    if (c == '<')
        return true;

    return false;
}

bool _isRightCarrot(char c) {
    if (c == '>')
        return true;

    return false;
}

и так далее для остальных специальных символов.

Я также попробовал тот же подход, что и существующий код в методе parse:

std::list<string> parse(const std::string& args) {

    std::stringstream ain(args);            // iterates over the input string
    ain >> std::noskipws;                   // ensures not to skip whitespace
    std::list<std::string> oargs;           // list of strings where we will store the tokens

    std::stringstream currentArg("");
    currentArg >> std::noskipws;

    // current state
    enum State {
            InArg,          // scanning the string currently
            InArgQuote,     // scanning the string that started with a quote currently 
            OutOfArg        // not scanning the string currently
    };
    State currentState = OutOfArg;

    char currentQuoteChar = '\0';   // used to differentiate between ' and "
                                    // ex. "sample'text" 

    char c;
    std::stringstream ss;
    std::string s;
    // iterate character by character through input string
    while(!ain.eof() && (ain >> c)) {

            // if current character is a quote
            if(_isQuote(c)) {
                    switch(currentState) {
                            case OutOfArg:
                                    currentArg.str(std::string());
                            case InArg:
                                    currentState = InArgQuote;
                                    currentQuoteChar = c;
                                    break;
                            case InArgQuote:
                                    if (c == currentQuoteChar)
                                            currentState = InArg;
                                    else
                                            currentArg << c;
                                    break;
                    }
            }
            // if current character is whitespace
            else if (_isWhitespace(c)) {
                        switch(currentState) {
                            case InArg:
                                    oargs.push_back(currentArg.str());
                                    currentState = OutOfArg;
                                    break;
                            case InArgQuote:
                                    currentArg << c;
                                    break;
                            case OutOfArg:
                                    // nothing
                                    break;
                    }
            }
            // if current character is escape character
            else if (_isEscape(c)) {
                    switch(currentState) {
                            case OutOfArg:
                                    currentArg.str(std::string());
                                    currentState = InArg;
                            case InArg:
                            case InArgQuote:
                                    if (ain.eof())
                                    {
                                            currentArg << c;
                                            throw(std::runtime_error("Found Escape Character at end of file."));
                                    }
                                    else {
                                            char c1 = c;
                                            ain >> c;
                                            if (c != '\"')
                                                    currentArg << c1;
                                            ain.unget();
                                            ain >> c;
                                            currentArg << c;
                                    }
                                    break;
                    }
            }

Что я добавил в методе parse:

            // if current character is left carrot (<)
            else if(_isLeftCarrot(c)) {
                    // convert from char to string and push onto list
                    ss << c;
                    ss >> s;
                    oargs.push_back(s);
            }
            // if current character is right carrot (>)
            else if(_isRightCarrot(c)) {
                    ss << c;
                    ss >> s;
                    oargs.push_back(s);
            }
.
.
.
            else {
                    switch(currentState) {
                            case InArg:
                            case InArgQuote:
                                    currentArg << c;
                                    break;
                            case OutOfArg:
                                    currentArg.str(std::string());
                                    currentArg << c;
                                    currentState = InArg;
                                    break;
                    }
            }
    }

    if (currentState == InArg) {
            oargs.push_back(currentArg.str());
            s.clear();
    }
    else if (currentState == InArgQuote)
            throw(std::runtime_error("Starting quote has no ending quote."));

    return oargs;
}

parse вернет список строк токенов.

Однако у меня возникают проблемы с конкретным контрольным примером, когда специальный символ прикрепляется к концу ввода.Например, ввод

foo-bar&

вернет этот список: [{&},{foo-bar}] вместо того, что я хочу: [{foo-bar},{&}]

Я пытаюсь это исправитьвопрос.Я новичок в C ++, поэтому любой совет вместе с некоторыми объяснениями будет очень полезен.

1 Ответ

0 голосов
/ 29 января 2019

Когда вы обрабатываете один из ваших символов, вам нужно делать то же, что и оригинальный код, когда он встречается с пробелом.Вам нужно взглянуть на currentState, а затем сохранить текущий аргумент, если вы находитесь в середине одного (и сбросить его, поскольку вы больше не в одном).

...