diff --git a/files/clibs/iup.dll b/files/clibs/iup.dll index 4695b31..3d28890 100644 Binary files a/files/clibs/iup.dll and b/files/clibs/iup.dll differ diff --git a/files/clibs/iup_mglplot.dll b/files/clibs/iup_mglplot.dll new file mode 100644 index 0000000..ed6edb5 Binary files /dev/null and b/files/clibs/iup_mglplot.dll differ diff --git a/files/clibs/iup_pplot.dll b/files/clibs/iup_pplot.dll index a4017ce..94e48aa 100644 Binary files a/files/clibs/iup_pplot.dll and b/files/clibs/iup_pplot.dll differ diff --git a/files/clibs/iup_scintilla.dll b/files/clibs/iup_scintilla.dll new file mode 100644 index 0000000..93ab6ce Binary files /dev/null and b/files/clibs/iup_scintilla.dll differ diff --git a/files/clibs/iupcd.dll b/files/clibs/iupcd.dll index bc28c33..0ee23ec 100644 Binary files a/files/clibs/iupcd.dll and b/files/clibs/iupcd.dll differ diff --git a/files/clibs/iupcontrols.dll b/files/clibs/iupcontrols.dll index 3f53d57..ded419d 100644 Binary files a/files/clibs/iupcontrols.dll and b/files/clibs/iupcontrols.dll differ diff --git a/files/clibs/iupgl.dll b/files/clibs/iupgl.dll index e5696b7..e89fb66 100644 Binary files a/files/clibs/iupgl.dll and b/files/clibs/iupgl.dll differ diff --git a/files/clibs/iupgtk.dll b/files/clibs/iupgtk.dll index 14d6ffd..833bbf9 100644 Binary files a/files/clibs/iupgtk.dll and b/files/clibs/iupgtk.dll differ diff --git a/files/clibs/iupim.dll b/files/clibs/iupim.dll index 6d4e98f..5a2057d 100644 Binary files a/files/clibs/iupim.dll and b/files/clibs/iupim.dll differ diff --git a/files/clibs/iupimglib.dll b/files/clibs/iupimglib.dll index 4654c8b..4cf91d6 100644 Binary files a/files/clibs/iupimglib.dll and b/files/clibs/iupimglib.dll differ diff --git a/files/clibs/iuplua51.dll b/files/clibs/iuplua51.dll index 22ca3b9..8a7a66b 100644 Binary files a/files/clibs/iuplua51.dll and b/files/clibs/iuplua51.dll differ diff --git a/files/clibs/iuplua_mglplot51.dll b/files/clibs/iuplua_mglplot51.dll new file mode 100644 index 0000000..4591eae Binary files /dev/null and b/files/clibs/iuplua_mglplot51.dll differ diff --git a/files/clibs/iuplua_pplot51.dll b/files/clibs/iuplua_pplot51.dll index b391753..a2606de 100644 Binary files a/files/clibs/iuplua_pplot51.dll and b/files/clibs/iuplua_pplot51.dll differ diff --git a/files/clibs/iuplua_scintilla51.dll b/files/clibs/iuplua_scintilla51.dll new file mode 100644 index 0000000..44b3998 Binary files /dev/null and b/files/clibs/iuplua_scintilla51.dll differ diff --git a/files/clibs/iupluacd51.dll b/files/clibs/iupluacd51.dll index 9fe2735..9b25c7c 100644 Binary files a/files/clibs/iupluacd51.dll and b/files/clibs/iupluacd51.dll differ diff --git a/files/clibs/iupluacontrols51.dll b/files/clibs/iupluacontrols51.dll index 462b37b..fc46d8d 100644 Binary files a/files/clibs/iupluacontrols51.dll and b/files/clibs/iupluacontrols51.dll differ diff --git a/files/clibs/iupluagl51.dll b/files/clibs/iupluagl51.dll index 9d1959e..fe16be8 100644 Binary files a/files/clibs/iupluagl51.dll and b/files/clibs/iupluagl51.dll differ diff --git a/files/clibs/iupluaim51.dll b/files/clibs/iupluaim51.dll index be0833d..6c40922 100644 Binary files a/files/clibs/iupluaim51.dll and b/files/clibs/iupluaim51.dll differ diff --git a/files/clibs/iupluaimglib51.dll b/files/clibs/iupluaimglib51.dll index b9a4bf0..d2fca5e 100644 Binary files a/files/clibs/iupluaimglib51.dll and b/files/clibs/iupluaimglib51.dll differ diff --git a/files/clibs/iupluaole51.dll b/files/clibs/iupluaole51.dll index cda8aa8..9f17e0b 100644 Binary files a/files/clibs/iupluaole51.dll and b/files/clibs/iupluaole51.dll differ diff --git a/files/clibs/iupluatuio51.dll b/files/clibs/iupluatuio51.dll index fd7d2e3..46e1556 100644 Binary files a/files/clibs/iupluatuio51.dll and b/files/clibs/iupluatuio51.dll differ diff --git a/files/clibs/iupluaweb51.dll b/files/clibs/iupluaweb51.dll index 351275f..9b52548 100644 Binary files a/files/clibs/iupluaweb51.dll and b/files/clibs/iupluaweb51.dll differ diff --git a/files/clibs/iupole.dll b/files/clibs/iupole.dll index 8d59dea..54a7314 100644 Binary files a/files/clibs/iupole.dll and b/files/clibs/iupole.dll differ diff --git a/files/clibs/iuptuio.dll b/files/clibs/iuptuio.dll index 3e78083..f816cb9 100644 Binary files a/files/clibs/iuptuio.dll and b/files/clibs/iuptuio.dll differ diff --git a/files/clibs/iupweb.dll b/files/clibs/iupweb.dll index a89dd68..c0c5aa0 100644 Binary files a/files/clibs/iupweb.dll and b/files/clibs/iupweb.dll differ diff --git a/files/clibs/lpeg.dll b/files/clibs/lpeg.dll index c8b70fa..6ca7102 100755 Binary files a/files/clibs/lpeg.dll and b/files/clibs/lpeg.dll differ diff --git a/files/docs/iup/iup-3.5_Docs.chm b/files/docs/iup/iup-3.8_Docs.chm similarity index 51% rename from files/docs/iup/iup-3.5_Docs.chm rename to files/docs/iup/iup-3.8_Docs.chm index 7977792..795b620 100644 Binary files a/files/docs/iup/iup-3.5_Docs.chm and b/files/docs/iup/iup-3.8_Docs.chm differ diff --git a/files/docs/lpeg/lpeg.html b/files/docs/lpeg/lpeg.html index 42d29a4..b31d575 100755 --- a/files/docs/lpeg/lpeg.html +++ b/files/docs/lpeg/lpeg.html @@ -1,28 +1,27 @@ - + "//www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +
LPeg is a new pattern-matching library for Lua, based on - + Parsing Expression Grammars (PEGs). This text is a reference manual for the library. For a more formal treatment of LPeg, as well as some discussion about its implementation, see - + A Text Pattern-Matching Tool based on Parsing Expression Grammars. (You may also be interested in my -talk about LPeg +talk about LPeg given at the III Lua Workshop.)
@@ -87,7 +86,7 @@lpeg.P(string)string literallylpeg.P(number)number characterslpeg.P(n)n characterslpeg.S(string)string (Set)lpeg.R("xy")lpeg.utfR(cp1, cp2)cp1 and
+ cp2patt^nn repetitions of pattpatt^-n("" - patt)#pattpatt but consumes no inputlpeg.B(patt)patt behind the current position,
+ consuming no inputAs a very simple example, @@ -129,18 +134,19 @@
-lpeg.P(1)
-(which can be written as lpeg.P(-1)
+(which can be written as lpeg.P(-1),
or simply -1 for operations expecting a pattern)
matches an empty string only if it cannot match a single character;
-so, it succeeds only at the subject's end.
+so, it succeeds only at the end of the subject.
LPeg also offers the re module,
which implements patterns following a regular-expression style
(e.g., [09]+).
-(This module is 200 lines of Lua code,
-and of course uses LPeg to parse regular expressions.)
+(This module is 270 lines of Lua code,
+and of course it uses LPeg to parse regular expressions and
+translate them to regular LPeg patterns.)
lpeg.match (pattern, subject [, init])captured values
+or the captured values
(if the pattern captured any value).
An optional numeric argument init makes the match
-starts at that position in the subject string.
-As usual in Lua libraries,
+start at that position in the subject string.
+As in the Lua standard libraries,
a negative value counts from the end.
lpeg.type (value)lpeg.version ()lpeg.version-Returns a string with the running version of LPeg. +A string (not a function) with the running version of LPeg. +
+ +lpeg.setmaxstack (max)+Sets a limit for the size of the backtrack stack used by LPeg to +track calls and choices. +(The default limit is 400.) +Most well-written patterns need little backtrack levels and +therefore you seldom need to change this limit; +before changing it you should try to rewrite your +pattern to avoid the need for extra space. +Nevertheless, a few useful patterns may overflow. +Also, with recursive grammars, +subjects with deep recursion may also need larger limits.
@@ -216,7 +236,7 @@lpeg.P (value)If the argument is a string, -it is translated to a pattern that matches literally the string. +it is translated to a pattern that matches the string literally.
@@ -227,9 +247,10 @@
lpeg.P (value)
If the argument is a negative number -n,
the result is a pattern that
-succeeds only if the input string does not have n characters:
-It is equivalent to the unary minus operation
-applied over the pattern corresponding to the (non-negative) value n.
+succeeds only if the input string has less than n characters left:
+lpeg.P(-n)
+is equivalent to -lpeg.P(n)
+(see the unary minus operation).
@@ -254,6 +275,22 @@
lpeg.P (value)lpeg.B(patt)
+Returns a pattern that
+matches only if the input string at the current position
+is preceded by patt.
+Pattern patt must match only strings
+with some fixed length,
+and it cannot contain captures.
+
+Like the and predicate, +this pattern never consumes any input, +independently of success or failure. +
+lpeg.R ({range})@@ -294,6 +331,15 @@
lpeg.S (string)lpeg.utfR (cp1, cp2)
+Returns a pattern that matches a valid UTF-8 byte sequence
+representing a code point in the range [cp1, cp2].
+The range is limited by the natural Unicode limit of 0x10FFFF,
+but may include surrogates.
+
lpeg.V (v)This operation creates a non-terminal (a variable) @@ -337,14 +383,15 @@
#pattpatt,
but without consuming any input,
independently of success or failure.
-(This pattern is equivalent to
+(This pattern is called an and predicate
+and it is equivalent to
&patt in the original PEG notation.)
+
-When it succeeds,
-#patt produces all captures produced by patt.
-
-pattpatt1 + patt2patt1 - patt2
-Returns a pattern equivalent to !patt2 patt1.
+Returns a pattern equivalent to !patt2 patt1
+in the origial PEG notation.
This pattern asserts that the input does not match
patt2 and then matches patt1.
+When successful,
+this pattern produces all captures from patt1.
+It never produces any capture from patt2
+(as either patt2 fails or
+patt1 - patt2 fails).
+
If both patt1 and patt2 are
character sets,
@@ -436,14 +492,14 @@
patt^n
If n is nonnegative,
this pattern is
-equivalent to pattn patt*.
-It matches at least n occurrences of patt.
+equivalent to pattn patt*:
+It matches n or more occurrences of patt.
Otherwise, when n is negative,
-this pattern is equivalent to (patt?)-n.
-That is, it matches at most -n
+this pattern is equivalent to (patt?)-n:
+It matches at most |n|
occurrences of patt.
+It is equivalent to the following grammar in standard PEG notation: +
++ S <- 'a' B / 'b' A / '' + A <- 'a' S / 'b' A A + B <- 'b' S / 'a' B B +
-A capture is a pattern that creates values -(the so called semantic information) when it matches. +A capture is a pattern that produces values +(the so called semantic information) +according to what it matches. LPeg offers several kinds of captures, which produces values based on matches and combine these values to produce new values. @@ -539,21 +604,22 @@
| Operation | What it Produces |
lpeg.C(patt) |
- the match for patt | the match for patt plus all captures
+ made by patt |
lpeg.Carg(n) |
the value of the nth extra argument to
lpeg.match (matches the empty string) |
lpeg.Cb(name) |
+|
lpeg.Cb(key) |
the values produced by the previous
- group capture named name
+ group capture named key
(matches the empty string) |
lpeg.Cc(values) |
the given values (matches the empty string) |
lpeg.Cf(patt, func) |
- a folding of the captures from patt |
lpeg.Cg(patt, [name]) |
+ folding capture (deprecated) |
lpeg.Cg(patt [, key]) |
the values produced by patt,
- optionally tagged with name |
lpeg.Cp() |
the current position (matches the empty string) |
lpeg.Cs(patt) |
@@ -564,22 +630,27 @@ |
patt / string |
string, with some marks replaced by captures
of patt |
patt / number |
+ the n-th value captured by patt,
+or no value when number is zero. |
patt / table |
table[c], where c is the (first)
capture of patt |
patt / function |
the returns of function applied to the captures
of patt |
patt % function |
+ produces no value;
+ it accummulates the captures from patt
+ into the previous capture through function
+ |
lpeg.Cmt(patt, function) |
the returns of function applied to the captures
of patt; the application is done at match time |
-A capture pattern produces its values every time it succeeds.
-For instance,
-a capture inside a loop produces as many values as matched by the loop.
-A capture produces a value only when it succeeds.
+A capture pattern produces its values only when it succeeds.
For instance,
the pattern lpeg.C(lpeg.P"a"^-1)
produces the empty string when there is no "a"
@@ -587,21 +658,27 @@
lpeg.C("a")^-1
does not produce any value when there is no "a"
(because the pattern "a" fails).
+A pattern inside a loop or inside a recursive structure
+produces values for each match.
Usually,
-LPeg evaluates all captures only after (and if) the entire match succeeds.
-At match time it only gathers enough information
-to produce the capture values later.
-As a particularly important consequence,
-most captures cannot affect the way a pattern matches a subject.
+LPeg does not specify when (and if) it evaluates its captures.
+(As an example,
+consider the pattern lpeg.P"a" / func / 0.
+Because the "division" by 0 instructs LPeg to throw away the
+results from the pattern,
+it is not specified whether LPeg will call func.)
+Therefore, captures should avoid side effects.
+Moreover,
+captures cannot affect the way a pattern matches a subject.
The only exception to this rule is the
so-called match-time capture.
When a match-time capture matches,
it forces the immediate evaluation of all its nested captures
and then calls its corresponding function,
-which tells whether the match succeeds and also
+which defines whether the match succeeds and also
what values are produced.
lpeg.Carg (n)lpeg.Cb (name)lpeg.Cb (key)
Creates a back capture.
This pattern matches the empty string and
produces the values produced by the most recent
-group capture named name.
+group capture named key
+(where key can be any Lua value).
Most recent means the last complete outermost -group capture with the given name. +group capture with the given key. A Complete capture means that the entire pattern -corresponding to the capture has matched. +corresponding to the capture has matched; +in other words, the back capture is not nested inside the group. An Outermost capture means that the capture is not inside -another complete capture. +another complete capture that does not contain the back capture itself.
++In the same way that LPeg does not specify when it evaluates captures, +it does not specify whether it reuses +values previously produced by the group +or re-evaluates them. +
-lpeg.Cc ({value})lpeg.Cc ([value, ...])Creates a constant capture. This pattern matches the empty string and @@ -654,62 +739,23 @@
lpeg.Cc ({value})lpeg.Cf (patt, func)
-Creates an fold capture.
-If patt produces a list of captures
-C1 C2 ... Cn,
-this capture will produce the value
-func(...func(func(C1, C2), C3)...,
- Cn),
-that is, it will fold
-(or accumulate, or reduce)
-the captures from patt using function func.
-
-This capture assumes that patt should produce
-at least one capture with at least one value (of any type),
-which becomes the initial value of an accumulator.
-(If you need a specific initial value,
-you may prefix a constant capture to patt.)
-For each subsequent capture
-LPeg calls func
-with this accumulator as the first argument and all values produced
-by the capture as extra arguments;
-the value returned by this call
-becomes the new value for the accumulator.
-The final value of the accumulator becomes the captured value.
-
-As an example, -the following pattern matches a list of numbers separated -by commas and returns their addition: -
-
--- matches a numeral and captures its value
-number = lpeg.R"09"^1 / tonumber
-
--- matches a list of numbers, captures their values
-list = number * ("," * number)^0
-
--- auxiliary function to add two numbers
-function add (acc, newvalue) return acc + newvalue end
-
--- folds the list of numbers adding them
-sum = lpeg.Cf(list, add)
-
--- example of use
-print(sum:match("10,30,43")) --> 83
-
+Creates a fold capture.
+This construction is deprecated;
+use an accumulator pattern instead.
+In general, a fold like
+lpeg.Cf(p1 * p2^0, func)
+can be translated to
+(p1 * (p2 % func)^0).
-lpeg.Cg (patt [, name])lpeg.Cg (patt [, key])
Creates a group capture.
It groups all values returned by patt
into a single capture.
-The group may be anonymous (if no name is given)
-or named with the given name.
+The group may be anonymous (if no key is given)
+or named with the given key
+(which can be any non-nil Lua value).
@@ -748,13 +794,13 @@
lpeg.Cs (patt)lpeg.Ct (patt)
Creates a table capture.
-This capture creates a table and puts all values from all anonymous captures
+This capture returns a table with all values from all anonymous captures
made by patt inside this table in successive integer keys,
starting at 1.
Moreover,
for each named capture group created by patt,
the first value of the group is put into the table
-with the group name as its key.
+with the group key as its key.
The captured value is only the table.
patt / stringpatt.
The sequence %0 stands for the whole match.
The sequence %% stands for a single %.
+
+
+
+patt / number
+Creates a numbered capture.
+For a non-zero number,
+the captured value is the n-th value
+captured by patt.
+When number is zero,
+there are no captured values.
+
patt / tablepatt / tableCreates a query capture. It indexes the given table using as key the first value captured by @@ -798,17 +856,110 @@
patt / functionpatt % function
+Creates an accumulator capture.
+This pattern behaves similarly to a
+function capture,
+with the following differences:
+The last captured value before patt
+is added as a first argument to the call;
+the return of the function is adjusted to one single value;
+that value replaces the last captured value.
+Note that the capture itself produces no values;
+it only changes the value of its previous capture.
+
+As an example, +let us consider the problem of adding a list of numbers. +
+
+-- matches a numeral and captures its numerical value
+number = lpeg.R"09"^1 / tonumber
+
+-- auxiliary function to add two numbers
+function add (acc, newvalue) return acc + newvalue end
+
+-- matches a list of numbers, adding their values
+sum = number * ("," * number % add)^0
+
+-- example of use
+print(sum:match("10,30,43")) --> 83
+
+
+First, the initial number captures a number;
+that first capture will play the role of an accumulator.
+Then, each time the sequence comma-number
+matches inside the loop there is an accumulator capture:
+It calls add with the current value of the
+accumulator—which is the last captured value, created by the
+first number— and the value of the new number,
+and the result of the call (the sum of the two numbers)
+replaces the value of the accumulator.
+At the end of the match,
+the accumulator with all sums is the final value.
+
+As another example, +consider the following code fragment: +
+
+local name = lpeg.C(lpeg.R("az")^1)
+local p = name * (lpeg.P("^") % string.upper)^-1
+print(p:match("count")) --> count
+print(p:match("count^")) --> COUNT
+
+
+In the match against "count",
+as there is no "^",
+the optional accumulator capture does not match;
+so, the match results in its sole capture, a name.
+In the match against "count^",
+the accumulator capture matches,
+so the function string.upper
+is called with the previous captured value (created by name)
+plus the string "^";
+the function ignores its second argument and returns the first argument
+changed to upper case;
+that value then becomes the first and only
+capture value created by the match.
+
+Due to the nature of this capture, +you should avoid using it in places where it is not clear +what is the "previous" capture, +such as directly nested in a string capture +or a numbered capture. +(Note that these captures may not need to evaluate +all their subcaptures to compute their results.) +Moreover, due to implementation details, +you should not use this capture directly nested in a +substitution capture. +You should also avoid a direct nesting of this capture inside +a folding capture (deprecated), +as the folding will try to fold each individual accumulator capture. +A simple and effective way to avoid all these issues is +to enclose the whole accumulation composition +(including the capture that generates the initial value) +into an anonymous group capture. +
+ +lpeg.Cmt(patt, function)
Creates a match-time capture.
Unlike all other captures,
-this one is evaluated immediately when a match occurs.
+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.
-The function gets as arguments the entire subject,
+The given function gets as arguments the entire subject,
the current position (after the match of patt),
plus any capture values produced by patt.
lpeg.Cmt(patt, function)lpeg.Cmt(patt, function)+This example shows a very simple but complete program +that builds and uses a pattern: +
+
+local lpeg = require "lpeg"
+
+-- matches a word followed by end-of-string
+p = lpeg.R"az"^1 * -1
+
+print(p:match("hello")) --> 6
+print(lpeg.match(p, "hello")) --> 6
+print(p:match("1 hello")) --> nil
+
+
+The pattern is simply a sequence of one or more lower-case letters
+followed by the end of string (-1).
+The program calls match both as a method
+and as a function.
+In both sucessful cases,
+the match returns
+the index of the first character after the match,
+which is the string length plus one.
+
+This example parses a list of name-value pairs and returns a table +with those pairs: +
+
+lpeg.locale(lpeg) -- adds locale entries into 'lpeg' table
+
+local space = lpeg.space^0
+local name = lpeg.C(lpeg.alpha^1) * space
+local sep = lpeg.S(",;") * space
+local pair = name * "=" * space * name * sep^-1
+local list = lpeg.Ct("") * (pair % rawset)^0
+t = list:match("a=b, c = hi; next = pi")
+ --> { a = "b", c = "hi", next = "pi" }
+
+
+Each pair has the format name = name followed by
+an optional separator (a comma or a semicolon).
+The list pattern then folds these captures.
+It starts with an empty table,
+created by a table capture matching an empty string;
+then for each a pair of names it applies rawset
+over the accumulator (the table) and the capture values (the pair of names).
+rawset returns the table itself,
+so the accumulator is always the table.
+
-The following code splits a string using a given pattern
+The following code builds a pattern that
+splits a string using a given pattern
sep as a separator:
@@ -852,7 +1062,8 @@Splitting a string
First the function ensures thatsepis a proper pattern. The patternelemis a repetition of zero of more arbitrary characters as long as there is not a match against -the separator. It also captures its result. +the separator. +It also captures its match. The patternpmatches a list of elements separated bysep. @@ -861,8 +1072,8 @@Splitting a string
If the split results in too many values, it may overflow the maximum number of values that can be returned by a Lua function. -In this case, -we should collect these values in a table: +To avoid this problem, +we can collect these values in a table:function split (s, sep) @@ -897,7 +1108,7 @@Searching for a pattern
This grammar has a straight reading: -it matches
por skips one character and tries again. +its sole rule matchespor skips one character and tries again.@@ -906,25 +1117,27 @@
Searching for a pattern
we can add position captures to the pattern:-local I = lpeg.Cp() +local Cp = lpeg.Cp() function anywhere (p) - return lpeg.P{ I * p * I + 1 * lpeg.V(1) } + return lpeg.P{ Cp * p * Cp + 1 * lpeg.V(1) } end + +print(anywhere("world"):match("hello world!")) --> 7 12Another option for the search is like this:
-local I = lpeg.Cp() +local Cp = lpeg.Cp() function anywhere (p) - return (1 - lpeg.P(p))^0 * I * p * I + return (1 - lpeg.P(p))^0 * Cp * p * Cp endAgain the pattern has a straight reading: it skips as many characters as possible while not matching
p, -and then matchesp(plus appropriate captures). +and then matchespplus appropriate captures.@@ -982,36 +1195,6 @@
Global substitution
-Name-value lists
--This example parses a list of name-value pairs and returns a table -with those pairs: -
--lpeg.locale(lpeg) - -local space = lpeg.space^0 -local name = lpeg.C(lpeg.alpha^1) * space -local sep = lpeg.S(",;") * space -local pair = lpeg.Cg(name * "=" * space * name) * sep^-1 -local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset) -t = list:match("a=b, c = hi; next = pi") --> { a = "b", c = "hi", next = "pi" } ---Each pair has the format
- -name = namefollowed by -an optional separator (a comma or a semicolon). -Thepairpattern encloses the pair in a group pattern, -so that the names become the values of a single capture. -Thelistpattern then folds these captures. -It starts with an empty table, -created by a table capture matching an empty string; -then for each capture (a pair of names) it appliesrawset-over the accumulator (the table) and the capture values (the pair of names). -rawsetreturns the table itself, -so the accumulator is always the table. -Comma-Separated Values (CSV)
This example breaks a string into comma-separated values, @@ -1037,89 +1220,15 @@
Comma-Separated Values (CSV)
ending with a newline or the string end (-1). - -UTF-8 and Latin 1
-It is not difficult to use LPeg to convert a string from -UTF-8 encoding to Latin 1 (ISO 8859-1): +As it is, +the previous pattern returns each field as a separated result. +If we add a table capture in the definition of
- -record, +the pattern will return instead a single table +containing all fields:--- convert a two-byte UTF-8 sequence to a Latin 1 character -local function f2 (s) - local c1, c2 = string.byte(s, 1, 2) - return string.char(c1 * 64 + c2 - 12416) -end - -local utf8 = lpeg.R("\0\127") - + lpeg.R("\194\195") * lpeg.R("\128\191") / f2 - -local decode_pattern = lpeg.Cs(utf8^0) * -1 ---In this code, -the definition of UTF-8 is already restricted to the -Latin 1 range (from 0 to 255). -Any encoding outside this range (as well as any invalid encoding) -will not match that pattern. -
- --As the definition of
-decode_patterndemands that -the pattern matches the whole input (because of the -1 at its end), -any invalid string will simply fail to match, -without any useful information about the problem. -We can improve this situation redefiningdecode_pattern-as follows: --local function er (_, i) error("invalid encoding at position " .. i) end - -local decode_pattern = lpeg.Cs(utf8^0) * (-1 + lpeg.P(er)) ---Now, if the pattern
- - -utf8^0stops -before the end of the string, -an appropriate error function is called. -UTF-8 and Unicode
--We can extend the previous patterns to handle all Unicode code points. -Of course, -we cannot translate them to Latin 1 or any other one-byte encoding. -Instead, our translation results in a array with the code points -represented as numbers. -The full code is here: -
---- decode a two-byte UTF-8 sequence -local function f2 (s) - local c1, c2 = string.byte(s, 1, 2) - return c1 * 64 + c2 - 12416 -end - --- decode a three-byte UTF-8 sequence -local function f3 (s) - local c1, c2, c3 = string.byte(s, 1, 3) - return (c1 * 64 + c2) * 64 + c3 - 925824 -end - --- decode a four-byte UTF-8 sequence -local function f4 (s) - local c1, c2, c3, c4 = string.byte(s, 1, 4) - return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 -end - -local cont = lpeg.R("\128\191") -- continuation byte - -local utf8 = lpeg.R("\0\127") / string.byte - + lpeg.R("\194\223") * cont / f2 - + lpeg.R("\224\239") * cont * cont / f3 - + lpeg.R("\240\244") * cont * cont * cont / f4 - -local decode_pattern = lpeg.Ct(utf8^0) * -1 ++local record = lpeg.Ct(field * (',' * field)^0) * (lpeg.P'\n' + -1)@@ -1129,7 +1238,7 @@Lua's long strings
and ends at the first occurrence of]=*]with exactly the same number of equal signs. If the opening brackets are followed by a newline, -this newline is discharged +this newline is discarded (that is, it is not part of the string). @@ -1141,18 +1250,19 @@Lua's long strings
-open = "[" * lpeg.Cg(lpeg.P"="^0, "init") * "[" * lpeg.P"\n"^-1 -close = "]" * lpeg.C(lpeg.P"="^0) * "]" +equals = lpeg.P"="^0 +open = "[" * lpeg.Cg(equals, "init") * "[" * lpeg.P"\n"^-1 +close = "]" * lpeg.C(equals) * "]" closeeq = lpeg.Cmt(close * lpeg.Cb("init"), function (s, i, a, b) return a == b end) -string = open * m.C((lpeg.P(1) - closeeq)^0) * close / - function (o, s) return s end +string = open * lpeg.C((lpeg.P(1) - closeeq)^0) * close / 1The
openpattern matches[=*[, capturing the repetitions of equal signs in a group namedinit; it also discharges an optional newline, if present. -Theclosepattern matches]=*]. +Theclosepattern matches]=*], +also capturing the repetitions of equal signs. Thecloseeqpattern first matchesclose; then it uses a back capture to recover the capture made by the previousopen, @@ -1162,10 +1272,8 @@Lua's long strings
Thestringpattern starts with anopen, then it goes as far as possible until matchingcloseeq, and then matches the finalclose. -The final function capture simply consumes -the captures made byopenandclose-and returns only the middle capture, -which is the string contents. +The final numbered capture simply discards +the capture made byclose. @@ -1181,17 +1289,17 @@Arithmetic expressions
-- Lexical Elements local Space = lpeg.S(" \n\t")^0 local Number = lpeg.C(lpeg.P"-"^-1 * lpeg.R("09")^1) * Space -local FactorOp = lpeg.C(lpeg.S("+-")) * Space -local TermOp = lpeg.C(lpeg.S("*/")) * Space +local TermOp = lpeg.C(lpeg.S("+-")) * Space +local FactorOp = lpeg.C(lpeg.S("*/")) * Space local Open = "(" * Space local Close = ")" * Space -- Grammar local Exp, Term, Factor = lpeg.V"Exp", lpeg.V"Term", lpeg.V"Factor" G = lpeg.P{ Exp, - Exp = lpeg.Ct(Factor * (FactorOp * Factor)^0); - Factor = lpeg.Ct(Term * (TermOp * Term)^0); - Term = Number + Open * Exp * Close; + Exp = lpeg.Ct(Term * (TermOp * Term)^0); + Term = lpeg.Ct(Factor * (FactorOp * Factor)^0); + Factor = Number + Open * Exp * Close; } G = Space * G * -1 @@ -1223,7 +1331,7 @@Arithmetic expressions
end -- small example -print(evalExp"3 + 5*9 / (1+1) - 12") --> 13.5 +print(evalExp"3 + 5*9 / (1+1) - 12") --> 13.5@@ -1245,21 +1353,21 @@
Arithmetic expressions
-- Grammar local V = lpeg.V G = lpeg.P{ "Exp", - Exp = lpeg.Cf(V"Factor" * lpeg.Cg(FactorOp * V"Factor")^0, eval); - Factor = lpeg.Cf(V"Term" * lpeg.Cg(TermOp * V"Term")^0, eval); - Term = Number / tonumber + Open * V"Exp" * Close; + Exp = V"Term" * (TermOp * V"Term" % eval)^0; + Term = V"Factor" * (FactorOp * V"Factor" % eval)^0; + Factor = Number / tonumber + Open * V"Exp" * Close; } -- small example -print(lpeg.match(G, "3 + 5*9 / (1+1) - 12")) --> 13.5 +print(lpeg.match(G, "3 + 5*9 / (1+1) - 12")) --> 13.5
-Note the use of the fold (accumulator) capture.
+Note the use of the accumulator capture.
To compute the value of an expression,
-the accumulator starts with the value of the first factor,
+the accumulator starts with the value of the first term,
and then applies eval over
the accumulator, the operator,
-and the new factor for each repetition.
+and the new term for each repetition.
LPeg -source code.
+source code. + ++Probably, the easiest way to install LPeg is with +LuaRocks. +If you have LuaRocks installed, +the following command is all you need to install LPeg: +
$ luarocks install lpeg
-Copyright © 2008 Lua.org, PUC-Rio. +Copyright © 2007-2023 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, @@ -1309,12 +1424,6 @@
-$Id: lpeg.html,v 1.54 2008/10/10 19:07:32 roberto Exp $ -
-
re Module
-The re Module
+The re module
(provided by file re.lua in the distribution)
supports a somewhat conventional regex syntax
for pattern usage within LPeg.
@@ -57,49 +56,57 @@
re Modulep represents an arbitrary pattern;
num represents a number ([0-9]+);
name represents an identifier
-([a-zA-Z][a-zA-Z0-9]*).
+([a-zA-Z][a-zA-Z0-9_]*).
Constructions are listed in order of decreasing precedence.
| Syntax | Description |
( p ) | grouping |
& p | and predicate |
! p | not predicate |
p1 p2 | concatenation |
p1 / p2 | ordered choice |
p ? | optional match |
p * | zero or more repetitions |
p + | one or more repetitions |
p^num |
+ exactly num repetitions |
p^+num |
+ at least num repetitions |
p^-num |
+ at most num repetitions |
(name <- p)+ | grammar |
'string' | literal string |
"string" | literal string |
[class] | character class |
. | any character |
%name |
pattern defs[name] or a pre-defined pattern |
name | non terminal |
<name> | non terminal |
{} | position capture |
{ p } | simple capture |
{: p :} | anonymous group capture |
{:name: p :} | named group capture |
{~ p ~} | substitution capture |
=name | back reference - |
p ? | optional match |
p * | zero or more repetitions |
p + | one or more repetitions |
p^num | exactly n repetitions |
p^+num |
- at least n repetitions |
p^-num |
- at most n repetitions |
{| p |} | table capture |
=name | back reference |
p -> 'string' | string capture |
p -> "string" | string capture |
p -> {} | table capture |
p -> num | numbered capture |
p -> name | function/query/string capture
equivalent to p / defs[name] |
p => name | match-time capture
equivalent to lpeg.Cmt(p, defs[name]) |
& p | and predicate |
! p | not predicate |
p1 p2 | concatenation |
p1 / p2 | ordered choice |
(name <- p)+ | grammar |
p ~> name | fold capture +(deprecated) |
p >> name | accumulator capture
+equivalent to (p % defs[name]) |
Any space appearing in a syntax description can be
-replaced by zero or more space characters and Lua-style comments
+replaced by zero or more space characters and Lua-style short comments
(-- until end of line).
re.find (subject, pattern [, init])Searches the given pattern in the given subject. If it finds a match, -returns the index where this occurrence starts, -plus the captures made by the pattern (if any). +returns the index where this occurrence starts and +the index where it ends. Otherwise, returns nil.
+
+An optional numeric argument init makes the search
+starts at that position in the subject string.
+As usual in Lua libraries,
+a negative value counts from the end.
+
re.gsub (subject, pattern, replacement)
+Does a global substitution,
+replacing all occurrences of pattern
+in the given subject by replacement.
+
re.match (subject, pattern)-Matches the given pattern against the given subject. +Matches the given pattern against the given subject, +returning all captures.
re.updatelocale ()re.updatelocale ()
+The next code shows a simple complete Lua program using
+the re module:
+
+local re = require"re"
+
+-- find the position of the first numeral in a string
+print(re.find("the number 423 is odd", "[0-9]+")) --> 12 14
+
+-- returns all words in a string
+print(re.match("the number 423 is odd", "({%a+} / .)*"))
+--> the number is odd
+
+-- returns the first numeral in a string
+print(re.match("the number 423 is odd", "s <- {%d+} / . s"))
+--> 423
+
+-- substitutes a dot for each vowel in a string
+print(re.gsub("hello World", "[aeiou]", "."))
+--> h.ll. W.rld
+
+
+
-As a simple example, -the following call will produce the same pattern produced by the +The following call will produce the same pattern produced by the Lua expression in the balanced parentheses example:
-b = re.compile[[ balanced <- "(" ([^()] / <balanced>)* ")" ]]
+b = re.compile[[ balanced <- "(" ([^()] / balanced)* ")" ]]
-rev = re.compile[[ R <- (!.) -> '' / ({.} <R>) -> '%2%1']]
+rev = re.compile[[ R <- (!.) -> '' / ({.} R) -> '%2%1']]
print(rev:match"0123456789") --> 9876543210
@@ -192,8 +237,8 @@
record = re.compile[[
- record <- ( <field> (',' <field>)* ) -> {} (%nl / !.)
- field <- <escaped> / <nonescaped>
+ record <- {| field (',' field)* |} (%nl / !.)
+ field <- escaped / nonescaped
nonescaped <- { [^,"%nl]* }
escaped <- '"' {~ ([^"] / '""' -> '"')* ~} '"'
]]
@@ -201,17 +246,85 @@ CSV decoder
Lua's long strings
-The next example mathes Lua long strings:
+The next example matches Lua long strings:
c = re.compile([[
- longstring <- ('[' {:eq: '='* :} '[' <close>) => void
- close <- ']' =eq ']' / . <close>
-]], {void = function () return true end})
+ longstring <- ('[' {:eq: '='* :} '[' close)
+ close <- ']' =eq ']' / . close
+]])
print(c:match'[==[]]===]]]]==]===[]') --> 17
+Abstract Syntax Trees
+
+This example shows a simple way to build an
+abstract syntax tree (AST) for a given grammar.
+To keep our example simple,
+let us consider the following grammar
+for lists of names:
+
+
+p = re.compile[[
+ listname <- (name s)*
+ name <- [a-z][a-z]*
+ s <- %s*
+]]
+
+
+Now, we will add captures to build a corresponding AST.
+As a first step, the pattern will build a table to
+represent each non terminal;
+terminals will be represented by their corresponding strings:
+
+
+c = re.compile[[
+ listname <- {| (name s)* |}
+ name <- {| {[a-z][a-z]*} |}
+ s <- %s*
+]]
+
+
+Now, a match against "hi hello bye"
+results in the table
+{{"hi"}, {"hello"}, {"bye"}}.
+
+
+For such a simple grammar,
+this AST is more than enough;
+actually, the tables around each single name
+are already overkilling.
+More complex grammars,
+however, may need some more structure.
+Specifically,
+it would be useful if each table had
+a tag field telling what non terminal
+that table represents.
+We can add such a tag using
+named group captures:
+
+
+x = re.compile[[
+ listname <- {| {:tag: '' -> 'list':} (name s)* |}
+ name <- {| {:tag: '' -> 'id':} {[a-z][a-z]*} |}
+ s <- ' '*
+]]
+
+
+With these group captures,
+a match against "hi hello bye"
+results in the following table:
+
+
+{tag="list",
+ {tag="id", "hi"},
+ {tag="id", "hello"},
+ {tag="id", "bye"}
+}
+
+
+
Indented blocks
This example breaks indented blocks into tables,
@@ -219,8 +332,8 @@
Indented blocks
p = re.compile[[
- block <- ({:ident:' '*:} <line>
- ((=ident !' ' <line>) / &(=ident ' ') <block>)*) -> {}
+ block <- {| {:ident:' '*:} line
+ ((=ident !' ' line) / &(=ident ' ') block)* |}
line <- {[^%nl]*} %nl
]]
@@ -259,14 +372,14 @@ Macro expander
p = re.compile[[
- text <- {~ <item>* ~}
- item <- <macro> / [^()] / '(' <item>* ')'
- arg <- ' '* {~ (!',' <item>)* ~}
- args <- '(' <arg> (',' <arg>)* ')'
+ text <- {~ item* ~}
+ item <- macro / [^()] / '(' item* ')'
+ arg <- ' '* {~ (!',' item)* ~}
+ args <- '(' arg (',' arg)* ')'
-- now we define some macros
- macro <- ('apply' <args>) -> '%1(%2)'
- / ('add' <args>) -> '%1 + %2'
- / ('mul' <args>) -> '%1 * %2'
+ macro <- ('apply' args) -> '%1(%2)'
+ / ('add' args) -> '%1 + %2'
+ / ('mul' args) -> '%1 * %2'
]]
print(p:match"add(mul(a,b), apply(f,x))") --> a * b + f(x)
@@ -290,54 +403,69 @@ Macro expander
with each %n replaced by the n-th argument.
+Patterns
+
+This example shows the complete syntax
+of patterns accepted by re.
+
+
+p = [=[
+
+pattern <- exp !.
+exp <- S (grammar / alternative)
+
+alternative <- seq ('/' S seq)*
+seq <- prefix*
+prefix <- '&' S prefix / '!' S prefix / suffix
+suffix <- primary S (([+*?]
+ / '^' [+-]? num
+ / '->' S (string / '{}' / name)
+ / '>>' S name
+ / '=>' S name) S)*
+
+primary <- '(' exp ')' / string / class / defined
+ / '{:' (name ':')? exp ':}'
+ / '=' name
+ / '{}'
+ / '{~' exp '~}'
+ / '{|' exp '|}'
+ / '{' exp '}'
+ / '.'
+ / name S !arrow
+ / '<' name '>' -- old-style non terminals
+
+grammar <- definition+
+definition <- name S arrow exp
+
+class <- '[' '^'? item (!']' item)* ']'
+item <- defined / range / .
+range <- . '-' [^]]
+
+S <- (%s / '--' [^%nl]*)* -- spaces and comments
+name <- [A-Za-z_][A-Za-z0-9_]*
+arrow <- '<-'
+num <- [0-9]+
+string <- '"' [^"]* '"' / "'" [^']* "'"
+defined <- '%' name
+
+]=]
+
+print(re.match(p, p)) -- a self description must match itself
+
License
-Copyright © 2008 Lua.org, PUC-Rio.
-
-
-Permission is hereby granted, free of charge,
-to any person obtaining a copy of this software and
-associated documentation files (the "Software"),
-to deal in the Software without restriction,
-including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software,
-and to permit persons to whom the Software is
-furnished to do so,
-subject to the following conditions:
-
+This module is part of the LPeg package and shares
+its license.
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software.
-
-
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-$Id: re.html,v 1.11 2008/10/10 18:14:06 roberto Exp $ -
-