diff options
-rw-r--r-- | README.md | 65 | ||||
-rw-r--r-- | examples/farthest.lua | 25 | ||||
-rw-r--r-- | examples/listId1.lua | 8 | ||||
-rw-r--r-- | examples/listId2.lua | 6 | ||||
-rw-r--r-- | examples/listIdRe1.lua | 8 | ||||
-rw-r--r-- | examples/tiny.lua | 4 | ||||
-rw-r--r-- | examples/typedlua/tlparser.lua | 4 | ||||
-rw-r--r-- | relabel.lua | 8 | ||||
-rw-r--r-- | testlabel.lua | 2 |
9 files changed, 90 insertions, 40 deletions
@@ -30,16 +30,15 @@ An error (a non-ordinary failure), by its turn, is produced | |||
30 | by the throw operator and may be caught by the recovery operator. | 30 | by the throw operator and may be caught by the recovery operator. |
31 | 31 | ||
32 | In LPegLabel, the result of an unsuccessful matching | 32 | In LPegLabel, the result of an unsuccessful matching |
33 | is a triple **nil, lab, sfail**, where **lab** | 33 | is a triple **nil, lab, errpos**, where **lab** |
34 | is the label associated with the failure, and | 34 | is the label associated with the failure, and |
35 | **sfail** is the suffix input being matched when | 35 | **errpos** is the input position being matched when |
36 | **lab** was thrown. | 36 | **lab** was thrown. |
37 | 37 | ||
38 | When **lab** is an ordinary failure and no error was thrown before, | 38 | When **lab** is an ordinary failure and no error was thrown before, |
39 | **sfail** is formed according to the farthest position where an | 39 | **errpos** is the farthest position where an ordinary failure occurred. |
40 | ordinary failure occurred. | ||
41 | In case **lab** is an ordinary failure and an error | 40 | In case **lab** is an ordinary failure and an error |
42 | was thrown before, **sfail** is the farthest suffix | 41 | was thrown before, **errpos** is the farthest input position |
43 | where an ordinary failure occurred after the last error. | 42 | where an ordinary failure occurred after the last error. |
44 | 43 | ||
45 | Below there is a brief summary of the new functions provided by LpegLabel: | 44 | Below there is a brief summary of the new functions provided by LpegLabel: |
@@ -51,12 +50,22 @@ Below there is a brief summary of the new functions provided by LpegLabel: | |||
51 | <tr><td><a href="#f-rec"><code>lpeglabel.Rec (p1, p2, l1 [, l2, ..., ln])</code></a></td> | 50 | <tr><td><a href="#f-rec"><code>lpeglabel.Rec (p1, p2, l1 [, l2, ..., ln])</code></a></td> |
52 | <td>Specifies a recovery pattern <code>p2</code> for <code>p1</code>, | 51 | <td>Specifies a recovery pattern <code>p2</code> for <code>p1</code>, |
53 | when the matching of <code>p1</code> gives one of the labels l1, ..., ln.</td></tr> | 52 | when the matching of <code>p1</code> gives one of the labels l1, ..., ln.</td></tr> |
53 | <tr><td><a href="#f-lc"><code>lpeglabel.Lc (p1, p2, l1, ..., ln)</code></a></td> | ||
54 | <td>Matches <code>p1</code> and tries to match <code>p2</code> | ||
55 | if the matching of <code>p1</code> gives one of l<sub>1</sub>, ..., l<sub>n</sub> | ||
56 | </td></tr> | ||
54 | <tr><td><a href="#re-t"><code>%{l}</code></a></td> | 57 | <tr><td><a href="#re-t"><code>%{l}</code></a></td> |
55 | <td>Syntax of <em>relabel</em> module. Equivalent to <code>lpeglabel.T(l)</code> | 58 | <td>Syntax of <em>relabel</em> module. Equivalent to <code>lpeglabel.T(l)</code> |
56 | </td></tr> | 59 | </td></tr> |
60 | <tr><td><a href="#re-pow"><code>p^l</code></a></td> | ||
61 | <td>Syntax sugar available at <em>relabel</em> for <code>p / %{l}</code> | ||
62 | </td></tr> | ||
57 | <tr><td><a href="#re-rec"><code>p1 //{l1 [, l2, ..., ln} p2</code></a></td> | 63 | <tr><td><a href="#re-rec"><code>p1 //{l1 [, l2, ..., ln} p2</code></a></td> |
58 | <td>Syntax of <em>relabel</em> module. Equivalent to <code>lpeglabel.Rec(p1, p2, l1, ..., ln)</code> | 64 | <td>Syntax of <em>relabel</em> module. Equivalent to <code>lpeglabel.Rec(p1, p2, l1, ..., ln)</code> |
59 | </td></tr> | 65 | </td></tr> |
66 | <tr><td><a href="#re-lc"><code>p1 /{l1, ..., ln} p2</code></a></td> | ||
67 | <td>Syntax of <em>relabel</em> module. Equivalent to <code>lpeg.Lc(p1, p2, l1, ..., ln)</code> | ||
68 | </td></tr> | ||
60 | <tr><td><a href="#re-line"><code>relabel.calcline(subject, i)</code></a></td> | 69 | <tr><td><a href="#re-line"><code>relabel.calcline(subject, i)</code></a></td> |
61 | <td>Calculates line and column information regarding position <i>i</i> of the subject</code> | 70 | <td>Calculates line and column information regarding position <i>i</i> of the subject</code> |
62 | </td></tr> | 71 | </td></tr> |
@@ -75,7 +84,7 @@ Returns a pattern that throws the label `l`. | |||
75 | A label must be an integer between 1 and 255. | 84 | A label must be an integer between 1 and 255. |
76 | 85 | ||
77 | This pattern always causes a failure, whose associated | 86 | This pattern always causes a failure, whose associated |
78 | position will be used to set **sfail**, no matter | 87 | position will be used to set **errpos**, no matter |
79 | whether this is the farthest failure position or not. | 88 | whether this is the farthest failure position or not. |
80 | 89 | ||
81 | 90 | ||
@@ -87,18 +96,45 @@ then the matching of `p2` is tried from the failure position of `p1`. | |||
87 | Otherwise, the result of the matching of `p1` is the pattern's result. | 96 | Otherwise, the result of the matching of `p1` is the pattern's result. |
88 | 97 | ||
89 | 98 | ||
99 | #### <a name="f-lc"></a><code>lpeglabel.Lc(p1, p2, l1, ..., ln)</code> | ||
100 | |||
101 | Returns a pattern equivalent to a *labeled ordered choice*. | ||
102 | If the matching of `p1` gives one of the labels `l1, ..., ln`, | ||
103 | then the matching of `p2` is tried from the same position. Otherwise, | ||
104 | the result of the matching of `p1` is the pattern's result. | ||
105 | |||
106 | <!--- | ||
107 | The labeled ordered choice `lpeg.Lc(p1, p2, 0)` is equivalent to the | ||
108 | regular ordered choice `p1 / p2`. | ||
109 | --> | ||
110 | |||
111 | Although PEG's ordered choice is associative, the labeled ordered choice is not. | ||
112 | When using this function, the user should take care to build a left-associative | ||
113 | labeled ordered choice pattern. | ||
114 | |||
115 | |||
90 | #### <a name="re-t"></a><code>%{l}</code> | 116 | #### <a name="re-t"></a><code>%{l}</code> |
91 | 117 | ||
92 | Syntax of *relabel* module. Equivalent to `lpeg.T(l)`. | 118 | Syntax of *relabel* module. Equivalent to `lpeg.T(l)`. |
93 | 119 | ||
94 | 120 | ||
95 | #### <a name="re-lc"></a><code>p1 //{l1, ..., ln} p2</code> | 121 | #### <a name="re-rec"></a><code>p1 //{l1, ..., ln} p2</code> |
96 | 122 | ||
97 | Syntax of *relabel* module. Equivalent to `lpeglabel.Rec(p1, p2, l1, ..., ln)`. | 123 | Syntax of *relabel* module. Equivalent to `lpeglabel.Rec(p1, p2, l1, ..., ln)`. |
98 | 124 | ||
99 | The `//{}` operator is left-associative. | 125 | The `//{}` operator is left-associative. |
100 | 126 | ||
101 | 127 | ||
128 | #### <a name="re-lc"></a><code>p1 /{l1, ..., ln} p2</code> | ||
129 | |||
130 | Syntax of *relabel* module. Equivalent to `lpeg.Lc(p1, p2, l1, ..., ln)`. | ||
131 | |||
132 | The `/{}` operator is left-associative. | ||
133 | |||
134 | A grammar can use both choice operators (`/` and `/{}`), | ||
135 | but a single choice can not mix them. That is, the parser of `relabel` | ||
136 | module will not recognize a pattern as `p1 / p2 /{l1} p3`. | ||
137 | |||
102 | 138 | ||
103 | #### <a name="re-line"></a><code>relabel.calcline (subject, i)</code> | 139 | #### <a name="re-line"></a><code>relabel.calcline (subject, i)</code> |
104 | 140 | ||
@@ -124,24 +160,25 @@ in the *examples* directory. | |||
124 | This example illustrates the new values returned | 160 | This example illustrates the new values returned |
125 | by the *match* function in case of an unsuccessful | 161 | by the *match* function in case of an unsuccessful |
126 | matching. As no error is thrown, when the matching | 162 | matching. As no error is thrown, when the matching |
127 | fails *sfail* represents the farthest suffix where | 163 | fails *errpos* represents the farthest suffix where |
128 | an ordinary failure occurred. | 164 | an ordinary failure occurred. |
129 | 165 | ||
130 | ```lua | 166 | ```lua |
131 | local m = require'lpeglabel' | 167 | local m = require'lpeglabel' |
132 | 168 | ||
133 | function matchPrint(p, s) | 169 | function matchPrint(p, s) |
134 | local r, lab, sfail = p:match(s) | 170 | local r, lab, errpos = p:match(s) |
135 | print("r: ", r, "lab: ", lab, "sfail: ", sfail) | 171 | print("r: ", r, "lab: ", lab, "errpos: ", errpos) |
136 | end | 172 | end |
137 | 173 | ||
138 | local p = m.P"a"^0 * m.P"b" + m.P"c" | 174 | local p = m.P"a"^0 * m.P"b" + m.P"c" |
139 | matchPrint(p, "abc") --> r: 3 lab: nil sfail: nil | 175 | matchPrint(p, "abc") --> r: 3 lab: nil errpos: nil |
140 | matchPrint(p, "c") --> r: 2 lab: nil sfail: nil | 176 | matchPrint(p, "c") --> r: 2 lab: nil errpos: nil |
141 | matchPrint(p, "aac") --> r: nil lab: 0 sfail: c | 177 | matchPrint(p, "aac") --> r: nil lab: 0 errpos: 3 |
142 | matchPrint(p, "xxc") --> r: nil lab: 0 sfail: xxc | 178 | matchPrint(p, "xxc") --> r: nil lab: 0 errpos: 1 |
143 | ``` | 179 | ``` |
144 | 180 | ||
181 | |||
145 | #### Matching a list of identifiers separated by commas | 182 | #### Matching a list of identifiers separated by commas |
146 | 183 | ||
147 | The following example defines a grammar that matches | 184 | The following example defines a grammar that matches |
diff --git a/examples/farthest.lua b/examples/farthest.lua index 692390f..9cbe03d 100644 --- a/examples/farthest.lua +++ b/examples/farthest.lua | |||
@@ -1,14 +1,27 @@ | |||
1 | local m = require'lpeglabel' | 1 | local m = require'lpeglabel' |
2 | 2 | ||
3 | function matchPrint(p, s) | 3 | function matchPrint(p, s) |
4 | local r, lab, sfail = p:match(s) | 4 | local r, lab, errpos = p:match(s) |
5 | print("r: ", r, "lab: ", lab, "sfail: ", sfail) | 5 | print("r: ", r, "lab: ", lab, "errpos: ", errpos) |
6 | end | ||
7 | |||
8 | function getSub (s, i) | ||
9 | if i then return s:sub(i) else return nil end | ||
10 | end | ||
11 | |||
12 | function matchPrint2(p, s) | ||
13 | local r, lab, ifail = p:match(s) | ||
14 | print("r: ", r, "lab: ", lab, "sfail: ", getSub(s, ifail)) | ||
6 | end | 15 | end |
7 | 16 | ||
8 | local p = m.P"a"^0 * m.P"b" + m.P"c" | 17 | local p = m.P"a"^0 * m.P"b" + m.P"c" |
9 | matchPrint(p, "abc") --> r: 3 lab: nil sfail: nil | 18 | matchPrint(p, "abc") --> r: 3 lab: nil errpos: nil |
10 | matchPrint(p, "c") --> r: 2 lab: nil sfail: nil | 19 | matchPrint(p, "c") --> r: 2 lab: nil errpos: nil |
11 | matchPrint(p, "aac") --> r: nil lab: 0 sfail: c | 20 | matchPrint(p, "aac") --> r: nil lab: 0 errpos: 3 |
12 | matchPrint(p, "xxc") --> r: nil lab: 0 sfail: xxc | 21 | matchPrint(p, "xxc") --> r: nil lab: 0 errpos: 1 |
13 | 22 | ||
14 | 23 | ||
24 | matchPrint2(p, "abc") --> r: 3 lab: nil sfail: nil | ||
25 | matchPrint2(p, "c") --> r: 2 lab: nil sfail: nil | ||
26 | matchPrint2(p, "aac") --> r: nil lab: 0 sfail: c | ||
27 | matchPrint2(p, "xxc") --> r: nil lab: 0 sfail: xxc | ||
diff --git a/examples/listId1.lua b/examples/listId1.lua index b7943c1..9bba783 100644 --- a/examples/listId1.lua +++ b/examples/listId1.lua | |||
@@ -13,14 +13,14 @@ local g = m.P{ | |||
13 | } | 13 | } |
14 | 14 | ||
15 | function mymatch (g, s) | 15 | function mymatch (g, s) |
16 | local r, e, sfail = g:match(s) | 16 | local r, e, pos = g:match(s) |
17 | if not r then | 17 | if not r then |
18 | local line, col = re.calcline(s, #s - #sfail) | 18 | local line, col = re.calcline(s, pos) |
19 | local msg = "Error at line " .. line .. " (col " .. col .. ")" | 19 | local msg = "Error at line " .. line .. " (col " .. col .. ")" |
20 | if e == 1 then | 20 | if e == 1 then |
21 | return r, msg .. ": expecting an identifier before '" .. sfail .. "'" | 21 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" |
22 | elseif e == 2 then | 22 | elseif e == 2 then |
23 | return r, msg .. ": expecting ',' before '" .. sfail .. "'" | 23 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" |
24 | else | 24 | else |
25 | return r, msg | 25 | return r, msg |
26 | end | 26 | end |
diff --git a/examples/listId2.lua b/examples/listId2.lua index 3ee89da..592dae3 100644 --- a/examples/listId2.lua +++ b/examples/listId2.lua | |||
@@ -25,11 +25,11 @@ local g = m.P{ | |||
25 | 25 | ||
26 | 26 | ||
27 | function mymatch (g, s) | 27 | function mymatch (g, s) |
28 | local r, e, sfail = g:match(s) | 28 | local r, e, pos = g:match(s) |
29 | if not r then | 29 | if not r then |
30 | local line, col = re.calcline(s, #s - #sfail) | 30 | local line, col = re.calcline(s, pos) |
31 | local msg = "Error at line " .. line .. " (col " .. col .. "): " | 31 | local msg = "Error at line " .. line .. " (col " .. col .. "): " |
32 | return r, msg .. terror[e] .. " before '" .. sfail .. "'" | 32 | return r, msg .. terror[e] .. " before '" .. s:sub(pos) .. "'" |
33 | end | 33 | end |
34 | return r | 34 | return r |
35 | end | 35 | end |
diff --git a/examples/listIdRe1.lua b/examples/listIdRe1.lua index 3098c66..d60706a 100644 --- a/examples/listIdRe1.lua +++ b/examples/listIdRe1.lua | |||
@@ -9,14 +9,14 @@ local g = re.compile[[ | |||
9 | ]] | 9 | ]] |
10 | 10 | ||
11 | function mymatch (g, s) | 11 | function mymatch (g, s) |
12 | local r, e, sfail = g:match(s) | 12 | local r, e, pos = g:match(s) |
13 | if not r then | 13 | if not r then |
14 | local line, col = re.calcline(s, #s - #sfail) | 14 | local line, col = re.calcline(s, pos) |
15 | local msg = "Error at line " .. line .. " (col " .. col .. ")" | 15 | local msg = "Error at line " .. line .. " (col " .. col .. ")" |
16 | if e == 1 then | 16 | if e == 1 then |
17 | return r, msg .. ": expecting an identifier before '" .. sfail .. "'" | 17 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" |
18 | elseif e == 2 then | 18 | elseif e == 2 then |
19 | return r, msg .. ": expecting ',' before '" .. sfail .. "'" | 19 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" |
20 | else | 20 | else |
21 | return r, msg | 21 | return r, msg |
22 | end | 22 | end |
diff --git a/examples/tiny.lua b/examples/tiny.lua index 734536c..cc718e7 100644 --- a/examples/tiny.lua +++ b/examples/tiny.lua | |||
@@ -90,9 +90,9 @@ local g = re.compile[[ | |||
90 | 90 | ||
91 | 91 | ||
92 | local function mymatch(g, s) | 92 | local function mymatch(g, s) |
93 | local r, e, sfail = g:match(s) | 93 | local r, e, pos = g:match(s) |
94 | if not r then | 94 | if not r then |
95 | local line, col = re.calcline(s, #s - #sfail) | 95 | local line, col = re.calcline(s, pos) |
96 | local msg = "Error at line " .. line .. " (col " .. col .. "): " | 96 | local msg = "Error at line " .. line .. " (col " .. col .. "): " |
97 | return r, msg .. terror[e].msg | 97 | return r, msg .. terror[e].msg |
98 | end | 98 | end |
diff --git a/examples/typedlua/tlparser.lua b/examples/typedlua/tlparser.lua index a301fa6..2ede2eb 100644 --- a/examples/typedlua/tlparser.lua +++ b/examples/typedlua/tlparser.lua | |||
@@ -226,9 +226,9 @@ end | |||
226 | function tlparser.parse (subject, filename, strict, integer) | 226 | function tlparser.parse (subject, filename, strict, integer) |
227 | local errorinfo = {} | 227 | local errorinfo = {} |
228 | lpeg.setmaxstack(1000) | 228 | lpeg.setmaxstack(1000) |
229 | local ast, label, suffix = lpeg.match(G, subject, nil, errorinfo, strict, integer) | 229 | local ast, label, pos = lpeg.match(G, subject, nil, errorinfo, strict, integer) |
230 | if not ast then | 230 | if not ast then |
231 | local line, col = lineno(subject, string.len(subject) - string.len(suffix)) | 231 | local line, col = lineno(subject, pos) |
232 | local error_msg = string.format("%s:%d:%d: ", filename, line, col) | 232 | local error_msg = string.format("%s:%d:%d: ", filename, line, col) |
233 | if label ~= 0 then | 233 | if label ~= 0 then |
234 | error_msg = error_msg .. tlerror.errors[label].msg | 234 | error_msg = error_msg .. tlerror.errors[label].msg |
diff --git a/relabel.lua b/relabel.lua index 642b0fe..abb3c7f 100644 --- a/relabel.lua +++ b/relabel.lua | |||
@@ -45,7 +45,7 @@ local errinfo = { | |||
45 | 45 | ||
46 | {"ExpPattOrClose", "expected a pattern or closing '}' after '{'"}, | 46 | {"ExpPattOrClose", "expected a pattern or closing '}' after '{'"}, |
47 | 47 | ||
48 | {"ExpNum", "expected a number after '^', '+' or '-' (no space)"}, | 48 | {"ExpNumName", "expected a number, '+', '-' or a name (no space) after '^'"}, |
49 | {"ExpCap", "expected a string, number, '{}' or name after '->'"}, | 49 | {"ExpCap", "expected a string, number, '{}' or name after '->'"}, |
50 | 50 | ||
51 | {"ExpName1", "expected the name of a rule after '=>'"}, | 51 | {"ExpName1", "expected the name of a rule after '=>'"}, |
@@ -245,7 +245,7 @@ local function getlab (f) | |||
245 | if not tlabels[f] then | 245 | if not tlabels[f] then |
246 | error("undefined label: " .. f) | 246 | error("undefined label: " .. f) |
247 | end | 247 | end |
248 | return mm.T(tlabels[f]) | 248 | return tlabels[f] |
249 | end | 249 | end |
250 | 250 | ||
251 | local exp = m.P{ "Exp", | 251 | local exp = m.P{ "Exp", |
@@ -269,7 +269,7 @@ local exp = m.P{ "Exp", | |||
269 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) | 269 | + m.Cg(m.C(m.S"+-" * m.R"09"^1) * m.Cc(mt.__pow) |
270 | + name * m.Cc"lab" | 270 | + name * m.Cc"lab" |
271 | ), | 271 | ), |
272 | "ExpNum") | 272 | "ExpNumName") |
273 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) | 273 | + "->" * expect(S * ( m.Cg((String + num) * m.Cc(mt.__div)) |
274 | + m.P"{}" * m.Cc(nil, m.Ct) | 274 | + m.P"{}" * m.Cc(nil, m.Ct) |
275 | + m.Cg(Def / getdef * m.Cc(mt.__div)) | 275 | + m.Cg(Def / getdef * m.Cc(mt.__div)) |
@@ -278,7 +278,7 @@ local exp = m.P{ "Exp", | |||
278 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), | 278 | + "=>" * expect(S * m.Cg(Def / getdef * m.Cc(m.Cmt)), |
279 | "ExpName1") | 279 | "ExpName1") |
280 | ) | 280 | ) |
281 | )^0, function (a,b,f) if f == "lab" then return a + getlab(b) else return f(a,b) end end ); | 281 | )^0, function (a,b,f) if f == "lab" then return a + mm.T(getlab(b)) else return f(a,b) end end ); |
282 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") | 282 | Primary = "(" * expect(m.V"Exp", "ExpPatt4") * expect(S * ")", "MisClose1") |
283 | + String / mm.P | 283 | + String / mm.P |
284 | + Class | 284 | + Class |
diff --git a/testlabel.lua b/testlabel.lua index d3d95b1..1be1343 100644 --- a/testlabel.lua +++ b/testlabel.lua | |||
@@ -1336,7 +1336,7 @@ g = re.compile([[ | |||
1336 | WRITE <- Sp 'write' | 1336 | WRITE <- Sp 'write' |
1337 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | 1337 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ |
1338 | Sp <- (%s / %nl)* | 1338 | Sp <- (%s / %nl)* |
1339 | ]], terror) | 1339 | ]]) |
1340 | 1340 | ||
1341 | s = [[ | 1341 | s = [[ |
1342 | n := 5;]] | 1342 | n := 5;]] |