Non-greedy search in lpeg without consuming the end match

Solution 1:

It's me again. I think you need better understanding about LPeg captures. Table capture (lpeg.Ct) is a capture that gathers your captures in a table. As there's no simple captures (lpeg.C) specified in NotTag rule, the final capture would become an empty table {}.

Once more, I recommend you start from lpeg.re because it's more intuitive.

local re = require('lpeg.re')
local inspect = require('inspect')

local g = re.compile[=[--lpeg
  tag       <- tag_start {| {NotTag} |} tag_end
  NotTag    <- &tag_end / . NotTag
  
  tag_start <- '[tag]'
  tag_end   <- '[/tag]'
]=]

print(inspect(g:match('[tag] foo [/tag]')))
-- output: { " foo " }

Additionally, S <- E2 / E1 S is not S <- E2 / E1 S*, these two are not equivalent.


However, if I were to do the same task, I won't try to use a non-greedy match, as non-greedy matches are always slower than greedy match.

tag <- tag_start {| {( !tag_end . (!'[' .)* )*} |} tag_end

Combining not-predicate and greedy matching is enough.