Правило PEG для определения прототипа функции - PullRequest
1 голос
/ 14 мая 2019

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

Это моя текущая реализация:

auto nameRule = x3::alpha >> *x3::alnum;
auto fcnPrototypeRule = nameRule >> *nameRule;
auto fcnRule = fcnPrototypeRule >> space >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(');');

Это моекод приложения:

class Parser {   

    public:
    std::string functionParser(const std::string& input) {
        std::string output;
        x3::phrase_parse(input.begin(), input.end(), fcnRule, space, output);
        return output;
    }
};

input is = "extern void myFunction ();"На выходе получается пустая строка.Я хотел получить прототип функции.

1 Ответ

0 голосов
/ 15 мая 2019

Похоже, ');' должно было быть ");"?

Кроме того, поскольку у вас есть шкипер (x3::space при вызове phrase_parse), нет особого смысла:

  • также укажите space в выражении вашего парсера (оно никогда не будет совпадать)
  • не заключать в оболочку nameRule внутри директивы lexeme или noskip. См. Также Проблемы со шкипером Boost Spirit

Итак, сначала попытайтесь заставить это работать:

std::string functionParser(const std::string& input) {
    namespace x3 = boost::spirit::x3;

    auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
    auto fcnPrototypeRule = nameRule >> *nameRule;
    auto fcnRule = fcnPrototypeRule >> x3::char_('(') >> -(nameRule % ',') >> x3::char_(");");
    std::string output;
    x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
    return output;
}

Однако вы заметите, что он возвращает ndn() ( Live On Coliru ).

Я думаю, что это в основном связано с тем, что ваша AS (std::string) не очень соответствует грамматике. Я бы сказал, что это похоже на то, что вы имеете в виду «сопоставить» вместо «разбора», и я бы использовал x3::raw, чтобы показать необработанное совпадение:

Live On Colriu

#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <iomanip>

std::string functionParser(const std::string& input) {
    namespace x3 = boost::spirit::x3;

    auto nameRule = x3::lexeme [x3::alpha >> *x3::alnum];
    auto fcnPrototypeRule = nameRule >> *nameRule;
    auto fcnRule = x3::raw[ fcnPrototypeRule >> '(' >> -(nameRule % ',') >> ')' >> ';' ];
    std::string output;
    x3::phrase_parse(input.begin(), input.end(), fcnRule, x3::space, output);
    return output;
}

int main() {
    for (auto s : {
        "extern void myFunction();",
        })
    {
        std::cout << std::quoted(s) << " -> " << std::quoted(functionParser(s)) << "\n";
    }
}
...