aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md125
1 files changed, 65 insertions, 60 deletions
diff --git a/README.md b/README.md
index fe7c14d..5e27796 100644
--- a/README.md
+++ b/README.md
@@ -31,8 +31,7 @@ character fails, and it is caught by an ordered choice.
31An error, by its turn, is produced by the throw operator 31An error, by its turn, is produced by the throw operator
32and may be caught by the recovery operator. 32and may be caught by the recovery operator.
33 33
34Below there is a brief summary 34Below there is a brief summary of the new functions provided by LpegLabel:
35of the new functions provided by LpegLabel:
36 35
37<table border="1"> 36<table border="1">
38<tbody><tr><td><b>Function</b></td><td><b>Description</b></td></tr> 37<tbody><tr><td><b>Function</b></td><td><b>Description</b></td></tr>
@@ -112,57 +111,11 @@ in the *examples* directory.
112The following example defines a grammar that matches 111The following example defines a grammar that matches
113a list of identifiers separated by commas. A label 112a list of identifiers separated by commas. A label
114is thrown when there is an error matching an identifier 113is thrown when there is an error matching an identifier
115or a comma: 114or a comma.
116 115
117```lua 116We use function `newError` to store error messages in a
118local m = require'lpeglabelrec' 117table and to return the index associated with each error message.
119local re = require'relabelrec'
120
121local g = m.P{
122 "S",
123 S = m.V"Id" * m.V"List",
124 List = -m.P(1) + (m.V"Comma" + m.T(2)) * (m.V"Id" + m.T(1)) * m.V"List",
125 Id = m.V"Sp" * m.R'az'^1,
126 Comma = m.V"Sp" * ",",
127 Sp = m.S" \n\t"^0,
128}
129
130function mymatch (g, s)
131 local r, e, sfail = g:match(s)
132 if not r then
133 local line, col = re.calcline(s, #s - #sfail)
134 local msg = "Error at line " .. line .. " (col " .. col .. ")"
135 if e == 1 then
136 return r, msg .. ": expecting an identifier before '" .. sfail .. "'"
137 elseif e == 2 then
138 return r, msg .. ": expecting ',' before '" .. sfail .. "'"
139 else
140 return r, msg
141 end
142 end
143 return r
144end
145
146print(mymatch(g, "one,two")) --> 8
147print(mymatch(g, "one two")) --> nil Error at line 1 (col 3): expecting ',' before ' two'
148print(mymatch(g, "one,\n two,\nthree,")) --> nil Error at line 3 (col 6): expecting an identifier before ''
149```
150 118
151In this example we could think about writing rule <em>List</em> as follows:
152```lua
153List = ((m.V"Comma" + m.T(2)) * (m.V"Id" + m.T(1)))^0,
154```
155
156but when matching this expression against the end of input
157we would get a failure whose associated label would be **2**,
158and this would cause the failure of the *whole* repetition.
159
160
161##### Mnemonics instead of numbers
162
163In the previous example we could have created a table
164with the error messages to improve the readability of the PEG.
165Below we rewrite the previous grammar following this approach:
166 119
167```lua 120```lua
168local m = require'lpeglabelrec' 121local m = require'lpeglabelrec'
@@ -203,19 +156,71 @@ print(mymatch(g, "one two")) --> nil Error at line 1 (col 3): expec
203print(mymatch(g, "one,\n two,\nthree,")) --> nil Error at line 3 (col 6): expecting an identifier before '' 156print(mymatch(g, "one,\n two,\nthree,")) --> nil Error at line 3 (col 6): expecting an identifier before ''
204``` 157```
205 158
159In this example we could think about writing rule <em>List</em> as follows:
160```lua
161List = ((m.V"Comma" + m.T(errComma)) * (m.V"Id" + m.T(errId)))^0,
162```
163
164but when matching this expression against the end of input
165we would get a failure whose associated label would be **errComma**,
166and this would cause the failure of the *whole* repetition.
167
168
169
206#### Error Recovery 170#### Error Recovery
207 171
208By using the recovery operator we can specify a recovery pattern that 172By using the `Rec` function we can specify a recovery pattern that
209should be matched when a label is thrown. After matching this pattern, 173should be matched when a label is thrown. After matching the recovery
210and possibly recording the error, the parser can continue parsing to 174pattern, and possibly recording the error, the parser will resume
211find more errors. 175the <em>regular</em> matching. For example, in the example below
176we expect to match rule `A`, but in case label 42 is thrown
177then we will try to match `recp`:
178```lua
179local m = require'lpeglabelrec'
212 180
213Below we rewrite the previous example to illustrate a recovery strategy. 181local recp = m.P"oast"
214Grammar `g` remains the same, but we add a recovery grammar `grec` that
215handles the labels thrown by `g`.
216 182
217arithmetic expression example and modify 183local g = m.P{
218the `expect` function to use the recovery operator for error recovery: 184 "S",
185 S = m.Rec(m.V"A", recp, 42) * ".",
186 A = m.P"t" * (m.P("est") + m.T(42))
187}
188
189print(g:match("test.")) --> 6
190
191print(g:match("toast.")) --> 7
192
193print(g:match("oast.")) --> nil 0 oast.
194
195print(g:match("toward.")) --> nil 0 ward.
196```
197When trying to match 'toast.', in rule `A` the first
198't' is matched, and then label 42 is thrown, with the associated
199inpux suffix 'oast.'. In rule `S` this label is caught
200and the recovery pattern matches 'oast', so pattern `'.'`
201matches the rest of the input.
202
203When matching 'oast.', pattern `m.P"t"` fails, and
204the result of the matching is <b>nil, 0, oast.</b>.
205
206When matching 'toward.', label 42 is throw, with the associated
207input suffix 'oward.'. The matching of the recovery pattern fails to,
208so the result of the matching is <b>nil, 0, ward.</b>.
209
210Usually, the recovery pattern is an expression that never fails.
211In the previous example, we could have used `(m.P(1) - m.P".")^0`
212as the recovery pattern.
213
214Below we rewrite the grammar that describes a list of identifiers
215to use a recovery strategy. Grammar `g` remains the same, but we add a
216recovery grammar `grec` that handles the labels thrown by `g`.
217
218In grammar `grec` we use functions `record` and `sync`.
219Function `record` gives us a pattern that captures two
220values: the current subject position (where a label was thrown)
221and the label itself. These values will be used to record
222all the errors found. Function `sync` give us synchronization
223pattern, that macthes the input
219 224
220```lua 225```lua
221local m = require'lpeglabelrec' 226local m = require'lpeglabelrec'