Дух: разрешение символа в начале, но не в середине

#parsing #boost-spirit #qi

#синтаксический анализ #boost-spirit #qi

Вопрос:

Я пытаюсь написать анализатор для идентификаторов javascript, пока это то, что у меня есть:

 // All this rules have string as attribute.
identifier_ = identifier_start
    >> 
    *(
        identifier_part >> -(qi::char_(".") > identifier_part)                      
     )
;
identifier_part =  (qi::alnum | qi::char_("_"));
identifier_start = qi::char_("a-zA-Z$_");
  

Этот анализатор отлично работает для списка «хороших идентификаторов» в моих тестах:

 "x__",
"__xyz",
"_",
"$",
"foo4_.bar_3",
"$foo.bar",
"$foo",
"_foo_bar.foo",
"_foo____bar.foo"
  

но у меня возникли проблемы с одним из неверных идентификаторов: foo$bar . Это должно завершиться неудачей, но это успех!! И синтезированный атрибут имеет значение "foo" .

Вот вывод отладки для foo$bar :

 <identifier_>
    <try>foo$bar</try>
    <identifier_start>
        <try>foo$bar</try>
        <success>oo$bar</success>
        <attributes>[[f]]</attributes>
    </identifier_start>
    <identifier_part>
        <try>oo$bar</try>
        <success>$bar</success>
        <attributes>[[f, o, o]]</attributes>
    </identifier_part>
    <identifier_part>
        <try>$bar</try>
        <fail/>
    </identifier_part>
  <success>$bar</success>
  <attributes>[[f, o, o]]</attributes>
</identifier_>
  

Чего я хочу, так это чтобы анализатор терпел неудачу при разборе, foo$bar но не при разборе $foobar .

Чего мне не хватает?

Ответ №1:

Вы не требуете, чтобы анализатор потреблял весь ввод.

Когда правило прекращает сопоставление перед $ знаком, оно возвращается с успехом, потому что ничто не говорит о том, что за ним не может следовать $ знак. Итак, вы хотели бы утверждать, что за ним не следует символ, который мог бы быть частью идентификатора:

 identifier_ = identifier_start
    >> 
    *(
        identifier_part >> -(qi::char_(".") > identifier_part)                      
     ) >> !identifier_start
;
  

Соответствующая директива distinct из репозитория Qi: http://www.boost.org/doc/libs/1_55_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/distinct.html

Комментарии:

1. Спасибо, я действительно не знаю, как я это пропустил. ; p