Не жадный разбор с fnparse - PullRequest
       2

Не жадный разбор с fnparse

1 голос
/ 04 декабря 2011

Я пытаюсь разобрать строки с помощью fnparse, и мне нужно действовать по-другому, если он находится в конце слова. Для этого у меня есть правила:

(def a-or-s
  (rep* (alt (lit \a) (lit \s))))

(def ends-with-s
  (conc a-or-s (lit \s)))

Я пытаюсь сопоставить строку "aas". Это, однако, не анализируется, потому что rep* является жадным и поглощает последний символ слова, а правило conc не работает. Как мне обойти это и правильно подобрать эти конструкции?

1 Ответ

1 голос
/ 04 декабря 2011

Для этого вам нужно будет использовать правило followed-by, в основном вы хотите многократно сопоставлять 'a' или 's', но без использования последнего токена. Вот код для этого:

(def a-or-s
  (lit-alt-seq "as")) ;; same as (alt (lit \a) (lit \s))

(def ends-with-s 
  (conc 
   (rep* (conc a-or-s (followed-by a-or-s))) 
   (lit \s)))

Мы можем реорганизовать этот код для создания нежадной версии rep* следующим образом:

(defn rep*? [subrule] 
  (rep* (conc subrule (followed-by subrule))))

Затем используйте его вместо rep*, и ваш исходный код должен работать как положено. Хотя попробовав это ...

user> (rule-match (conc (rep*? a-or-s) (lit \s)) identity #(identity %2) {:remainder "aaaaaaaasss"})
([(\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \a) (\a \s) (\s \s) (\s \s)] \s)

... вы можете спросить «что происходит с выходом?», Ну rep*? дает нам пары токенов, потому что это то, что мы просили. Это можно исправить, используя invisi-conc вместо conc:

(defn rep*? [subrule] 
  (rep* (invisi-conc subrule (followed-by subrule))))

user> (rule-match (conc (rep*? a-or-s) (lit \s)) identity #(identity %2) {:remainder "aaaaaaaasss"})
([\a \a \a \a \a \a \a \a \s \s] \s)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...