[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Elegant design for creating error messages in LPEG parser
- From: Sean Conner <sean@...>
- Date: Wed, 3 Apr 2019 20:50:47 -0400
It was thus said that the Great joy mondal once stated:
> Just a side question.
>
> Under what design consideration do we use 'Cmt(patt,f) ' vs 'patt/f' ?
>
> I noticed you used Cmt , why not 'patt/f' ?
The docs say this of lpeg.Cmt():
Creates a match-time capture. Unlike all other captures, this one is
evaluated immediately when a match occurs (***even if it is part of
a larger pattern that fails later***). It forces the immediate
evaluation of all its nested captures and then calls function.
(emphasis added)
If I didn't, the error checking wouldn't work as expected. Changing the
WS production to:
local WS = lpeg.P" "
+ lpeg.P"\t"
+ lpeg.P"\n" * lpeg.Carg(1)
/ function(state)
print(">>>",state.line)
state.line = state.line + 1
end
causes my code to produce the following output as an error:
Missing ']' at line 1 (start line 1)
even though I see the diagnostic print() statements printed three times:
>>> 1
>>> 2
>>> 3
I think it has something to do with lazy evaluation in LPEG in this case.
I've also used it to fail a pattern that would otherwise match. It is
possible to come up with a pattern that matches the numbers between 0 and
255 but it's quite involved and part of it looks like:
dec_octet = P"25" * R"05"
+ P"2" * P"04" * P"09"
+ P"1" * ...
I found it easier to use Cmt() instead:
local dec_octet = Cmt(DIGIT^1,function(_,position,capture)
local n = tonumber(capture)
if n < 256 then
return position
end
end)
When the string of digits is greater than 255, this returns nil, which
causes the match to fail. Doing this:
dec_octet = DIGIT^1
/ function(c)
local n = tonumber(c)
if n < 256 then
return c
end
end
won't cause the match to fail---instead it will return nil as the captured
data.
-spc