Lpeg Case Insensitive Match

61 views
Skip to first unread message

Scott Morgan

unread,
Jun 7, 2024, 11:45:38 AMJun 7
to lu...@googlegroups.com
I need a case-insensitive literal match and came up with this, which
seems to work:

Pi = function(pat)
local lpat = pat:lower()
local len = pat:len()
return Cmt(P(len), function(subj, pos) return
subj:lower() == lpat and pos; end)
end

print(P"test":match"test")
5
print(P"test":match"Test")
nil
print(Pi"test":match"Test")
5

But doesn't chain together:

print((P"test" * '='):match"test=")
6
print((Pi"test" * '='):match"test=")
nil

Am I on the right track? What am I missing?

Scott

Sean Conner

unread,
Jun 7, 2024, 3:47:17 PMJun 7
to 'Scott Morgan' via lua-l
It was thus said that the Great 'Scott Morgan' via lua-l once stated:
Yes you are (and it's a nice bit of code---certainly better than what I
came up with). I modified the code a bit to show you what's going on:

Pi = function(pat)
local lpat = pat:lower()
local len = pat:len()
return Cmt(P(len), function(subj, pos)
print(">>>",subj,pos)
return subj:lower() == lpat and pos
end)
end

foo = P"aaa "
bar = foo * Pi"test" * P"="
print(bar:match "aaa test=")

>>> aaa test= 9
nil

The subj parameter of Cmt() gets the entire string you are matching, not
just what P(len) returns. Instead, if you change the function to:

Pi = function(pat)
local lpat = pat:lower()
local len = pat:len()
return Cmt(P(len), function(subj, pos, capture)
print(">>>",subj,pos,capture)
return capture:lower() == lpat and pos
end)
end

>>> aaa test= 9 test
10

it works as intended. Despite the wording of the description of Cmt():

The given function gets as arguments the entire subject, the current
position (after the match of patt), plus any capture values produced
by patt.

you don't actually have to explicitly capture values in the pattern.

-spc

Scott Morgan

unread,
Jun 10, 2024, 9:21:29 AMJun 10
to lu...@googlegroups.com
On 07/06/2024 20:47, Sean Conner wrote:
> It was thus said that the Great 'Scott Morgan' via lua-l once stated:
>> I need a case-insensitive literal match
>>
>> ...
>>
>> Am I on the right track? What am I missing?
>
> Yes you are (and it's a nice bit of code---certainly better than what I
> came up with).
> ...
> The subj parameter of Cmt() gets the entire string you are matching, not
> just what P(len) returns.

Ah! Yes, I misunderstood the doc, thought the first arg was just the
matched string.

Pi = function(pat)
local lpat = pat:lower()
return Cmt(P(lpat:len()), function(_, pos, cap)
return cap:lower() == lpat and pos; end)
end

print((C(Pi"test") * P"=" * C(R"09" ^ 1)):match"Test=123")
Test 123
print((C(Pi"test") * P"=" * C(R"09" ^ 1)):match"TesX=123")
nil

Thank you, got it working.

Scott

Reply all
Reply to author
Forward
0 new messages