Я использую Boost.Spirit.Lex и .Qi для проекта простого калькулятора, и (как обычно) это доставляет мне некоторую боль при отладке и использовании. Отладка печатает:
<expression>
<try>boost::spirit::multi_pass::illegal_backtracking
Это исключение выброшено, и я не могу понять, почему. Я использую макросы в своем коде, и было бы больно приводить минимальный пример, поэтому я даю весь проект. Просто сделайте «make» в корне, а затем запустите ./sash, появится приглашение, если вы хотите протестировать, просто выполните «-echo $ 5-8».
Похоже, что Google не нашел подобных проблем с этим исключением …
Синтаксический анализатор находится в арифметическом /, и вызов синтаксического анализатора находится в конце arithmetic /valuator.cpp
Любой помогает очень ценить.
Ваш код не работает, потому что BOOST_SPIRIT_QI_DEBUG, а также on_error<>
кажется, что обработчик использует итераторы после того, как они могли быть признаны недействительными.
Если честно, я не совсем уверен, как это могло произойти.
AFAICT lexertl использует spirit::multipass<>
с split_functor
политика ввода и split_std_deque
политика хранения [1].
Теперь (к счастью?) Политика проверки buf_id_check
Это означает, что итератор будет проверять наличие недействительности во время разыменования.
Ожидается, что итераторы будут признаны недействительными, если
clear_queue
вызывается точно (например, из flush_multi_path
примитив в духовном хранилище)Честно говоря, я не вижу ни одного из этих двух условий. Быстрый и грязный
token_iterator_type clone = iter; // just to make it non-unique...
в evaluator.cpp
не имеет значения (исключая причину № 1)
Временное отключение docheck
реализация в buf_id_check_policy
заставил Вальгринда указать, что on_error<>
и BOOST_SPIRIT_DEBUG * вызывают недействительные ссылки на память. Комментирование и то и другое действительно устраняет все проблемы (и eval_expression
в настоящее время работает).
Однако это, вероятно, не ваше предпочтительное решение.
поскольку
multi_pass
эмуляция поведенияЯ быстро изменил код: https://github.com/sehe/sash-refactor/commits/master
совершить dec31496 sanity - lets do without macros
4 файла изменены, 59 вставок (+), 146 удалений (-)
совершить 6056574c dead code, excess scope, excess instantiation
5 файлов изменено, 38 вставок (+), 62 удалений (-)
совершить 99d441db remove lexer
9 файлов изменены, 25 вставок (+), 177 удалений (-)
Теперь вы обнаружите, что ваш код, как правило, намного проще, к тому же намного короче, не выходит за пределы multi_pass, и вы все равно можете иметь SPIRIT_DEBUG, а также on_error
управляемость 🙂 В итоге
Вот несколько примеров (без отладочной информации):
$ ./sash <<< '-echo $8-9'
-1
Warning: Empty environment variable "8-9".
$ ./sash <<< '-echo $8\*9'
72
Warning: Empty environment variable "8*9".
$ ./sash <<< '-echo $8\*(9-1)'
64
Warning: Empty environment variable "8*(9-1)".
$ ./sash <<< '-echo $--+-+8\*(9-1)'
-64
Warning: Empty environment variable "--+-+8*(9-1)".
[1] Которые, несмотря на свое название, буферы ранее видели токены в std::vector<>
Других решений пока нет …