I’m trying to parse strings with fnparse and I need to act on a character differently if it is at the end of a word. For this I have rules thus:
(def a-or-s
(rep* (alt (lit \a) (lit \s))))
(def ends-with-s
(conc a-or-s (lit \s)))
I try to match the string “aas”. This however doesn’t parse because the rep* is greedy and swallows up the last character of the word and the conc rule doesn’t work. How can I get round this and match these constructions properly?
For that you’ll need to use the
followed-byrule, basically you want to repeatedly match ‘a’ or ‘s’ but without consuming the last token. Here’s the code to do that:We can refactor that code to create a non-greedy version of
rep*like this:Then use it instead of
rep*and your original code should work as expected. After trying it though……you might ask “what’s happening to the output?”, well
rep*?is giving us pairs of tokens because that’s what we asked for. This can fixed usinginvisi-concinstead ofconc: