2014-09-02 2 views
1

У меня возникли проблемы с получением Духа, чтобы попробовать альтернативы. Я новичок в духе и, вероятно, делать что-то грубо неправильно, поэтому я извиняюсь за тянут вниз SNR, но любая помощь приветствуется:Новичок Дух не пытается альтернативы

Я использую грамматику, как следующее, чтобы соответствовать «классы символов»

'[' >> *(~ascii::char_("-]^") | (ascii::char_ >> '-' >>ascii::char_)) >> ']' 

Это соответствия [abc], но не [a-c]. Если я удалю первый вариант, то [a-c] совпадений. Разве Дух не должен повторять вторую альтернативу, когда первое не удается?

Спасибо,

Майк

ответ

2

Основная проблема заключается в том, что первая альтернатива делает матч - это просто не соответствует тому, что вы хотите. Как написано, ваш синтаксический анализатор соответствует последовательности из 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].

+0

Я боялся, что это будет ответ. Я написал много рекурсивных парсеров спуска вручную, и, когда я нахожу себя в углу, я возвращаюсь туда, где мог бы взять другую ветвь чередования. Похоже, что Antlr также хочет создать резервную копию этого примера и найти совпадение. Есть ли способ сказать Духу продолжать попытки, как это делает Antlr? – user2913094

+0

boost: spirit использует парсер PEG, который строго упорядочен и нетерпелив. Antlr использует парсер LL, который совершенно другой. «Откат» в парсере PEG относится только к точкам «|» альтернатив, а не к другим точкам. –

 Смежные вопросы

  • Нет связанных вопросов^_^