Устранение неоднозначности в простой грамматике Instaparse

[Также опубликовано в списке рассылки Instaparse, но также и здесь, так как я предполагаю, что это довольно общая проблема]

Рассмотрим грамматику

 D = (B|S)*
 S = 'S' B*
 B = 'B'

(Это версия Instaparse BNF...)

B может произойти сам по себе или после S; если последнее, то оно должно рассматриваться как часть выражения SER (без каламбура).

Пример:

(-> "D = (B|S)*
     S = 'S' B*
     B = 'B'"
    parser
    (parses "BSBB"))

;;=>
([:D [:B "B"] [:S "S"] [:B "B"] [:B "B"]]
 [:D [:B "B"] [:S "S" [:B "B"] [:B "B"]]]    ;; <------
 [:D [:B "B"] [:S "S" [:B "B"]] [:B "B"]])

Я бы хотел, чтобы совпадал только второй результат - так, чтобы B был включен в S, когда это возможно, и удалил другие опции. Что нужно сделать с моим парсером, чтобы сделать это изменение?

Больше примеров выражений показано в этой сущности.

1 ответ

Решение

Вы можете использовать отрицательный прогноз, чтобы постулировать, что совпадения S не должно сопровождаться действительным Bs:

(-> "

D = (B|S)*
S = 'S' B* !B
B = 'B'

"
insta/parser
(insta/parses "BSBB"))
;= ([:D [:B "B"] [:S "S" [:B "B"] [:B "B"]]])

Это работает для всех примеров (текущей версии) в вашей сути.

Другие вопросы по тегам