Вопрос по dynamically-generated, boost-spirit, rule, boost – C ++ Boost qi рекурсивное построение правил

4

[Похоже, мои объяснения и ожидания не совсем ясны, поэтому я добавил точность того, как я хотел бы использовать эту функцию в конце поста]

В настоящее время я работаю над грамматикой, используя повышение ци. У меня была конструкция цикла для правила, потому что мне нужно было построить его из элементов вектора. Я переписал его с простыми типами, и это выглядит так:

#include <string>

// using boost 1.43.0
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_eps.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace bqi = boost::spirit::qi;

typedef const char* Iterator;

// function that you can find [here][1]
template<typename P> void test_phrase_parser(char const* input, P const& p, bool full_match = true);

int main()
{
    // my working rule type:
    bqi::rule<Iterator, std::string()> myLoopBuiltRule;
    std::vector<std::string> v;
    std::vector<std::string>::const_iterator iv;

    v.push_back("abc");
    v.push_back("def");
    v.push_back("ghi");
    v.push_back("jkl");

    myLoopBuiltRule = (! bqi::eps);
    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()  [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }
    debug(myLoopBuiltRule);

    char s[] = "  abc ";

    test_phrase_parser(s, myLoopBuiltRule);
}

(Выглядит какВот не хочет заменяться соответствующей гиперссылкой, поэтому вот адрес для поиска функции test_phrase_parser ():http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/basics.html)

Все было к лучшему в лучшем из всех миров ... пока мне не пришлось передать аргумент этому правилу. Вот новый тип правила:

    // my not-anymore-working rule type:
    bqi::rule<Iterator, std::string(int*)> myLoopBuiltRule;

Тип 'int *' предназначен только для целей, мой реальный указатель адресован гораздо более сложному классу ... но все же простой указатель.

Я изменил свой цикл for соответственно, т.е.

    for(iv = v.begin() ; iv != v.end() ; iv++)
    {
        myLoopBuiltRule =
                myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
                | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]
                ;
    }

Мне пришлось добавить новое правило, потому что test_phrase_parser () не может угадать, какое значение нужно дать указателю int:

bqi::rule<Iterator> myInitialRule;

И измените все, что следует за циклом for:

myInitialRule = myLoopBuiltRule((int*)NULL);

debug(myLoopBuiltRule);

char s[] = "  abc ";

test_phrase_parser(s, myInitialRule);

Потом все рухнуло

/home/sylvain.darras/software/repository/software/external/include/boost/boost_1_43_0/boost/spirit/home/qi/nonterminal/rule.hpp:199: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&)

Тогда я сошел с ума и попробовал:

myLoopBuiltRule =
        myLoopBuiltRule.copy(bqi::_r1)  [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

->

error: no matching function for call to ‘boost::spirit::qi::rule<const c,har*, std::string(int*), boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type>::copy(const boost::phoenix::actor<boost::spirit::attribute<1> >&)’

Тогда я разозлился и написал:

myLoopBuiltRule =
        myLoopBuiltRule(bqi::_r1)   [ bqi::_val = bqi::_1 ]
        | bqi::string(*iv)      [ bqi::_val = bqi::_1 ]

Который компилируется, поскольку он совершенно синтаксически корректен, но который великолепно переполняет стек, потому что он счастливо, красиво, рекурсивно вызывает себя к смерти ...

Затем я сошел с ума и набрал:

myLoopBuiltRule =
        jf jhsgf jshdg fjsdgh fjsg jhsdg jhg sjfg jsgh df

Который, как вы, вероятно, ожидаете, не скомпилирован.

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

Будьте уверены, что любая помощь будет по-настоящему оценена.

PS: Большое спасибо hkaiser, который, не зная об этом, ответил на многие мои проблемы boost :: qi через google (но этот).

Дальнейшая информация:

Цель моего синтаксического анализатора - читать файлы, написанные на заданном языке L. Цель моего поста - распространять мой «контекст» (т. Е. Определения переменных и особенно постоянные значения, чтобы я мог вычислять выражения).

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

Итак, давайте рассмотрим псевдоалгоритм того, чего я хотел бы достичь:

LTypeList myTypes;
LTypeList::const_iterator iTypes;

bqi::rule<Iterator, LType(LContext*)> myLoopBuiltRule;

myLoopBuiltRule = (! bqi::eps);
for(iTypes = myTypes.begin() ; iTypes != myTypes.end() ; iTypes++)
{
    myLoopBuiltRule =
        myLoopBuiltRule.copy()(bqi::_r1)    [ bqi::_val = bqi::_1 ]
        | iTypes->getRule()(bqi::_r1)           [ bqi::_val = bqi::_1 ]
}

Это делается во время инициализации, а затем myLoopBuiltRule используется и повторно используется с другим LContext *, анализируя несколько типов. И поскольку некоторые типы L могут иметь границы, которые являются целочисленными выражениями, и что эти целочисленные выражения могут демонстрировать константы, я (думаю, что я) нуждаюсь в моем унаследованном атрибуте, чтобы обойти мой LContext и иметь возможность вычислить значение выражения.

Надеюсь, я прояснил свои намерения.

Хм. У меня есть ощущение, что я могу упустить какую-то «внутреннюю сложность» (читай: вы слишком хорошо сократили свой образец :)), но как насчет:coliru.stacked-crooked.com/... (срок действия компиляции истекает через Интернет, но вы можете запустить ее) sehe
@Sylv Я думаю, что этот вопрос может быть очень интересным, но, к сожалению, я не могу понять, что именно вы хотите. Не могли бы вы предоставить чуть менее упрощенный пример ввода и правил, которые вы хотите составить? llonesmiz
Спасибо. [К сожалению, я думаю, что ваш вариант использования подтвердил, что невозможно заменить унаследованный атрибут локальным, а также для «внешней» ссылки.]Я могу только сказать, что это главная причина, почему я склонен разделять синтаксический анализ и интерпретацию (источник -> [parsing] -> AST -> [compile] -> промежуточное представление -> [engine] -> требуемые эффекты :)). sehe
Argh. Теперь, когда вы укажете методологию написания компилятора, я должен признать, что упомянутое вами AST выглядит хорошей идеей ... что я должен был это сделать несколько месяцев назад. И это, кажется, решает другие скучные периферийные проблемы, которые у меня были в прошлом. Так что я не буду вас больше беспокоить и не буду занимать много времени. Спасибо вам и cv_and_he. Даже если я сомневаюсь в этом, я надеюсь, что смогу помочь вам в будущем. Sylv
Прежде всего, большое спасибо за вашу помощь и время, которое вы тратите на мой вопрос. К сожалению, когда я читаю ответ и комментарии ниже, я чувствую себя маленьким ребенком, разговаривающим со взрослыми ... Я не уверен, что смогу решить мою проблему с помощью данных предложений, потому что мне это кажется странным. Понятие, которое я понял, касается qi :: символов, но тогда не-это правильно: моя выборка слишком уменьшена ... Вот в чем смысл: цикл добавлен| bqi::string(*iv) на самом деле| another_rule_N(bqi::_r1), :-( Sylv

Ваш Ответ

1   ответ
2

Запись Я только расширил свой ответ еще несколькими информационными ссылками. В этом конкретном случае у меня есть догадка, что вы могли бытолько что сойти с трюк Nabialekа также заменяяунаследованный атрибут с соответствующимqi::locals<> вместо. Если у меня будет достаточно времени, я могу устроить демонстрацию позже.

Предостережения, излагающие проблему

Обращаем ваше внимание, что при копировании деревьев выражений прототипов и, в частности, выражений анализатора спирта возникают проблемы -будем создайте висячие ссылки, так как внутренние объекты не должны жить после конца содержащихся полных выражений. Смотрите BOOST_SPIRIT_AUTO наНоль до 60 миль в час за 2 секунды!

Также посмотрите эти ответы, которые также касаются построения / составления правил на лету (во время выполнения):

Генерация выражений анализатора Spirit из списка альтернативных выражений анализатораМогут ли быть настроены правила повышения духа который демонстрирует, как вернуть правила из функции, используяboost::proto::deepcopy (как BOOST_SPIRIT_AUTO, на самом деле)Набиалек Трик

В общем, я бы очень сильно советовалпротив объединение правил во время выполнения. Вместо этого, если вы хотите «добавить альтернативы» в правило во время выполнения, вы всегда можете использоватьqi::symbols<> вместо. Хитрость заключается вхранить правило в таблице символов и использоватьqi::lazy называть правило. В частности, это известно какНабиалек Трик.

У меня есть игрушечный синтаксический анализатор аргументов командной строки, который демонстрирует, как вы могли бы использовать эту идиому для сопоставления заданного во время выполнения набора аргументов командной строки:

https://gist.github.com/sehe/2a556a8231606406fe36Ограниченияqi::lazy, что дальше?

К несчастью,qi::lazy не поддерживаетунаследованные аргументы см. например

http://boost.2283326.n4.nabble.com/pass-inhertited-attributes-to-nabialek-trick-td2679066.html

Возможно, вам лучше написать собственный компонент парсера, как описано здесь:

http://boost-spirit.com/home/articles/qi-example/creating-your-own-parser-component-for-spirit-qi/

Я постараюсь найти время для разработки примера, который позже заменит унаследованные аргументы на qi :: locals.

У меня есть все основания полагать, что он любит отвечать, даже если он не уверен на 100%, что он прав, надеясь, что он может помочь. llonesmiz
Это просто вычисление типа результата выраженияrule(inh_attr) так же, как это рассчитываетсяВот и используя это как тип возврата функции феникса. (Я, кстати, llonesmiz). llonesmiz
Было ли что-то не так сэто? llonesmiz
@cv_and_he интересно читать, я не видел его раньше. Я должен буду прочитать это позже. Однако, на данный момент, судя по названию llonesmiz, я бы сказал, что шансы довольно хорошие, что в этом нет ничего плохого :) sehe
@cv_and_he это может быть правдой, но у меня есть хорошие основания (включая моего собственного свидетеля), что он также очень хорошо разбирается в Boost (и Spirit). Как я уже сказал, я посмотрю позже. Он выглядел как перекрестное решение пользовательского компонента синтаксического анализатора в сочетании с qi :: lazy. Я полагаюphx::cref часть - это подозрительная часть, поскольку она может предполагать, что время жизни переданных ссылок может быть неверным / удобным. Но сейчас семейное время. sehe

Похожие вопросы