I'm writing a grammar that includes exactly three alphabetic characters. Here's my code:
local l = require "lpeg"
l.locale(l)
local date = l.digit^1 * l.P'/' * l.digit^1 * l.P'/' * l.digit^1
local time = l.digit^1 * l.P':' * l.digit^1 * l.P':' * l.digit^1 * l.P':' * l.digit^1
local timezone = l.alpha^3
local stamp = l.P'[' * date * l.P' ' * time * l.P' ' * timezone * l.P']'
grammar = l.C(stamp)
The input I'm matching against is this:
[4/23/15 4:49:49:371 CDT]
How do I get the expression to match only three alphabetic characters in the timezone? The way this code works now is it will match three or more alphabetic characters.
Weird! Does this work?
local timezone = l.alpha*2
It seems to, but I can't find that syntax referenced anywhere here:
l.alpha*2
is l.alpha
*
l.P(2)
.
So no, that matches [a-z]..
.
See the output from lpeg.print(timezone)
to confirm that. (Note my use of ll
for the locale data. Putting it in the same table loses the original print
debugging function.)
> l=require"lpeg"
> ll=lpeg.locale()
> p=ll.alpha*2
> l.print(p)
[]
00: set [(41-5a)(61-7a)]-> FAIL
05: any * 2-> FAIL
06: end
> =p.match("099")
nil
> =p.match("EST")
4
> =p.match("E99")
4
The pattern you want is:
> function patcount(pat, min, max)
>> return -pat^(max + 1) * pat^min
>> end
> p=patcount(ll.alpha, 3, 3)
> lpeg.print(p)
[]
00: set [(41-5a)(61-7a)]-> 27
05: choice -> 27 (1)
06: set [(41-5a)(61-7a)]-> FAIL
11: set [(41-5a)(61-7a)]-> FAIL
16: set [(41-5a)(61-7a)]-> FAIL
21: span [(41-5a)(61-7a)]
26: failtwice
27: set [(41-5a)(61-7a)]-> FAIL
32: set [(41-5a)(61-7a)]-> FAIL
37: set [(41-5a)(61-7a)]-> FAIL
42: span [(41-5a)(61-7a)]
47: end
> =p:match("EST")
4
> return p:match("ES")
nil
> return p:match("ESTT")
nil
> return p:match("099")
nil
> return p:match("E99")
nil
The relevant documentation bit is -patt
.
As to the l.alpha*2
syntax that's explained by this quote from the manual.
All operations that expect a pattern as an argument may receive also strings, tables, numbers, booleans, or functions, which are translated to patterns according to the rules of function lpeg.P.
Which is to say that the operators convert non-patterns to patterns when one of the operands is a pattern already.
There's also the 'Match a fixed number of repetitions of a pattern' section (and the link) on the LpegRecipes lua-users.org wiki page. (But I haven't looked over that implementation at all and it looks more complicated than mine above.)