Основная проблема заключается в том, что первая альтернатива делает матч - это просто не соответствует тому, что вы хотите. Как написано, ваш синтаксический анализатор соответствует последовательности из 3 штук, причем средний - это повторяющийся шаблон, имеющий альтернативу в нем.
'[' // single char match
>> *(~ascii::char_("-]^") | (ascii::char_ >> '-' >>ascii::char_)) // complex pattern
>> ']' // single char match
Итак, давайте посмотрим, что происходит, когда вы пытаетесь соответствовать [a-c]
. Сначала вы соответствуете шаблону '['
, который преуспевает и уходит a-c]
. Итак, он смотрит на сложный шаблон, который он пытается совместить 0 или более раз. В этом *
повторите сначала сначала ~ascii::char_("-]^")
, что соответствует a
, поэтому успех уходит -c]
. Затем он повторяется, пытаясь снова сопоставить этот шаблон, который не срабатывает (-
не соответствует), поэтому он пытается использовать второй вариант, где ascii::char
соответствует -
, но '-'
не соответствует c
, поэтому он терпит неудачу. Таким образом, конец совпадения *
соответствует одному символу a
. Наконец, он пытается сопоставить ']'
, который выходит из строя против -
, поэтому общий матч терпит неудачу.
Чтение выше (если вы можете понять это) должен сделать это ясно, что вам нужно сделать - это необходимо, чтобы попытаться матч диапазона, прежде чем он пытается единственный матч обугленного в пределах *
цикла:
'[' >> *((ascii::char_ >> '-' >>ascii::char_) | ~ascii::char_("-]^")) >> ']'
Теперь он должен соответствовать как [abc]
, так и [a-c]
, а также таким вещам, как [a-cmx-z]
.
Я боялся, что это будет ответ. Я написал много рекурсивных парсеров спуска вручную, и, когда я нахожу себя в углу, я возвращаюсь туда, где мог бы взять другую ветвь чередования. Похоже, что Antlr также хочет создать резервную копию этого примера и найти совпадение. Есть ли способ сказать Духу продолжать попытки, как это делает Antlr? – user2913094
boost: spirit использует парсер PEG, который строго упорядочен и нетерпелив. Antlr использует парсер LL, который совершенно другой. «Откат» в парсере PEG относится только к точкам «|» альтернатив, а не к другим точкам. –