Boost.Spirit.X3 как предотвратить анализ токена по предыдущему правилу? - PullRequest
2 голосов
/ 06 апреля 2020

с учетом этой грамматики:

const auto grammar_def = x3::lit("start")
                        > x3::lit("{")
                        > (*(char_("a-zA-Z0-9\".{}=_~")))
                        > x3::lit("}") > x3::lit(";");

последний x3 :: lit ("}") используется (* (char _ ("a-zA- Z0-9 \ ". {} = _ ~"))) , поскольку он содержит "}"
, есть ли способ предотвратить это? Что-то вроде x3 :: lit ("}") более высокий приоритет при разборе?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Вы всегда можете написать собственный синтаксический анализатор, который работает как kleene star, но может возвращаться назад и также требует второго синтаксического анализатора, который также должен совпадать. Нечто подобное должно работать.

        template <class Left, class Right>
        struct backtracking : binary_parser<Left, Right, backtracking<Left, Right>>
        {
            using base = binary_parser<Left, Right, backtracking<Left, Right>>;
            backtracking(Left const& left, Right const& right)
                :  base(left, right)
            {
            }

            template<typename It, typename Ctx, typename Other>
            bool parse(It& f, It l, Ctx const& ctx, Other const& other, unused_type) const
            {
                auto end_it = l;
                while (end_it != f) {
                    auto save = f;
                    if (this->left.parse(f, end_it, ctx, other, unused)) {
                        if (this->right.parse(f, l, ctx, other, unused))
                            return true;
                    }
                    f = save;
                    --end_it;
                }
                return false;
            }
        };

const auto grammar_def = x3::lit("start")
                        > x3::lit("{")
                        > backtracking(
                             *(char_("a-zA-Z0-9\".{}=_~")), lit("}") >> lit(";"));
1 голос
/ 09 апреля 2020

Единственный способ, который я нашел, - это запретить клинской звезде совпадать с '}', если после ;.

const auto grammar_def = x3::lit("start")
                        > x3::lit("{")
                        > *(char_("a-zA-Z0-9\".{}=_~") >> !lit(';'))
                        > x3::lit("}") > x3::lit(";");
...