diff options
author | Sergio Medeiros <sqmedeiros@gmail.com> | 2015-03-23 15:09:08 -0300 |
---|---|---|
committer | Sergio Medeiros <sqmedeiros@gmail.com> | 2015-03-23 15:09:08 -0300 |
commit | f124b2d4449a13ac21af9581a44b4455d89eaddb (patch) | |
tree | e0486555ac811c5f712927f110bb7bcda8569adf /lpeglabel.html | |
parent | 0e93d536ba2d312502737cce2ab0cc21393c4842 (diff) | |
download | lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.tar.gz lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.tar.bz2 lpeglabel-f124b2d4449a13ac21af9581a44b4455d89eaddb.zip |
Renaming "re.lua" to "relabel.lua".
Adding examples, README and lpeglabel.html
Diffstat (limited to '')
-rw-r--r-- | lpeglabel.html | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/lpeglabel.html b/lpeglabel.html new file mode 100644 index 0000000..b38e900 --- /dev/null +++ b/lpeglabel.html | |||
@@ -0,0 +1,574 @@ | |||
1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" | ||
2 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | ||
3 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||
4 | <head> | ||
5 | <title>LPegLabLabel - Parsing Expression Grammars For Lua</title> | ||
6 | <link rel="stylesheet" | ||
7 | href="http://www.inf.puc-rio.br/~roberto/lpeg/doc.css" | ||
8 | type="text/css"/> | ||
9 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||
10 | </head> | ||
11 | <body> | ||
12 | |||
13 | <!-- $Id: lpeg.html,v 1.71 2013/04/11 19:17:41 roberto Exp $ --> | ||
14 | |||
15 | <div id="container"> | ||
16 | |||
17 | <div id="product"> | ||
18 | <div id="product_logo"> | ||
19 | <a href="https://github.com/sqmedeiros/lpeglabel"> | ||
20 | <img alt="LPeg logo" src="lpeg-128.gif"/></a> | ||
21 | |||
22 | </div> | ||
23 | <div id="product_name"><big><strong>LPegLabel</strong></big></div> | ||
24 | <div id="product_description"> | ||
25 | Parsing Expression Grammars For Lua with Labels, version 0.1 | ||
26 | </div> | ||
27 | </div> <!-- id="product" --> | ||
28 | |||
29 | <div id="main"> | ||
30 | |||
31 | <div id="navigation"> | ||
32 | <h1>LPeg</h1> | ||
33 | |||
34 | <ul> | ||
35 | <li><strong>Home</strong> | ||
36 | <ul> | ||
37 | <li><a href="#intro">Introduction</a></li> | ||
38 | <li><a href="#func">Functions</a></li> | ||
39 | <li><a href="#ex">Some Examples</a></li> | ||
40 | <li><a href="#download">Download</a></li> | ||
41 | <li><a href="#license">License</a></li> | ||
42 | </ul> | ||
43 | </li> | ||
44 | </ul> | ||
45 | </div> <!-- id="navigation" --> | ||
46 | |||
47 | <div id="content"> | ||
48 | |||
49 | |||
50 | <h2><a name="intro">Introduction</a></h2> | ||
51 | |||
52 | <p> | ||
53 | <em>LPegLabel</em> is an extension of the | ||
54 | <a href="http://www.inf.puc-rio.br/~roberto/lpeg/">LPeg</a> | ||
55 | library that provides an implementation of Parsing Expression | ||
56 | Grammars (PEGs) with labeled failures. Labels can be | ||
57 | used to signal different kinds of erros and to | ||
58 | specify which alternative in a labeled ordered choice | ||
59 | should handle a given label. Labels can also be combined | ||
60 | with the standard patterns of LPeg. | ||
61 | </p> | ||
62 | |||
63 | <p> | ||
64 | This document describes the new functions available | ||
65 | in LpegLabel and presents some examples of usage. | ||
66 | For a more detailed and formal discussion about | ||
67 | PEGs with labels please see | ||
68 | <a href="http://www.inf.puc-rio.br/~roberto/docs/sblp2013-1.pdf"> | ||
69 | Exception Handling for Error Reporting in Parsing Expression Grammars | ||
70 | </a> | ||
71 | and | ||
72 | <a href="http://arxiv.org/abs/1405.6646">Error Reporting in Parsing Expression Grammars</a>. | ||
73 | </p> | ||
74 | |||
75 | |||
76 | <p> | ||
77 | Below there is a brief summary of the new functions | ||
78 | provided by LpegLabel: | ||
79 | </p> | ||
80 | <table border="1"> | ||
81 | <tbody><tr><td><b>Function</b></td><td><b>Description</b></td></tr> | ||
82 | <tr><td><a href="#f-t"><code>lpeglabel.T (l<sub>1</sub>, ..., l<sub>n</sub>)</code></a></td> | ||
83 | <td>Throws labels <code>l<sub>1</sub>, ..., l<sub>n</sub></code></td></tr> | ||
84 | <tr><td><a href="#f-lc"><code>lpeglabel.Lc (p1, p2, l<sub>1</sub>, ..., l<sub>n</sub>)</code></a></td> | ||
85 | <td>Matches <code>p1</code> and tries to match <code>p2</code> | ||
86 | if the matching of <code>p1</code> gives one of l<sub>1</sub>, ..., l<sub>n</sub> | ||
87 | </td></tr> | ||
88 | <tr><td><a href="#re-t"><code>%{l<sub>1</sub>, ..., l<sub>n</sub>}</code></a></td> | ||
89 | <td>Syntax of <em>re</em> module. Equivalent to <code>lpeg.T(l<sub>1</sub>, ..., l<sub>n</sub>)</code> | ||
90 | </td></tr> | ||
91 | <tr><td><a href="#re-lc"><code>p1 /{l<sub>1</sub>, ..., l<sub>n</sub>} p2</code></a></td> | ||
92 | <td>Syntax of <em>re</em> module. Equivalent to <code>lpeg.Lc(p1, p2, l<sub>1</sub>, ..., l<sub>n</sub>)</code> | ||
93 | </td></tr> | ||
94 | <tr><td><a href="#re-setl"><code>re.setlabels (tlabel)</code></a></td> | ||
95 | <td>Allows to specicify a table with labels. They keys of | ||
96 | <code>tlabel</code> must be integers, and the associated values usually are strings. | ||
97 | </td></tr> | ||
98 | </tbody></table> | ||
99 | |||
100 | <p> | ||
101 | In case of an unsucessful matching, the <em>match</em> function now returns | ||
102 | <code>nil</code> plus a list of labels. These labels may be used to build | ||
103 | a good error message. | ||
104 | </p> | ||
105 | |||
106 | <h2><a name="func">Functions</a></h2> | ||
107 | |||
108 | |||
109 | <h3><a name="f-t"></a><code>lpeglabel.T(l<sub>1</sub>, ..., l<sub>n</sub>)</code></h3> | ||
110 | <p> | ||
111 | Returns a pattern that throws the list of labels <code>l<sub>1</sub>, ..., l<sub>n</sub></code>. | ||
112 | A label must be an integer between <code>0</code> and <code>31</code>. | ||
113 | |||
114 | The label <code>0</code> is equivalent to the regular failure of PEGs. | ||
115 | |||
116 | |||
117 | <h3><a name="f-lc"></a><code>lpeglabel.Lc(p1, p2, l<sub>1</sub>, ..., l<sub>n</sub>)</code></h3> | ||
118 | <p> | ||
119 | Returns a pattern equivalent to a <em>labeled ordered choice</em>. | ||
120 | If the matching of <code>p1</code> gives one of the labels <code>l<sub>1</sub>, ..., l<sub>n</sub></code>, | ||
121 | then the matching of <code>p2</code> is tried from the same position. Otherwise, | ||
122 | the result of the matching of <code>p1</code> is the pattern's result. | ||
123 | </p> | ||
124 | |||
125 | <p> | ||
126 | The labeled ordered choice <code>lpeg.Lc(p1, p2, 0)</code> is equivalent to the | ||
127 | regular ordered choice <code>p1 / p2</code>. | ||
128 | </p> | ||
129 | |||
130 | <p> | ||
131 | Although PEG's ordered choice is associative, the labeled ordered choice is not. | ||
132 | When using this function, the user should take care to build a left-associative | ||
133 | labeled ordered choice pattern. | ||
134 | </p> | ||
135 | |||
136 | |||
137 | <h3><a name="re-t"></a><code>%{l<sub>1</sub>, ..., l<sub>n</sub>}</code></h3> | ||
138 | <p> | ||
139 | Syntax of <em>re</em> module. Equivalent to <code>lpeg.T(l<sub>1</sub>, ..., l<sub>n</sub>)</code>. | ||
140 | </p> | ||
141 | |||
142 | |||
143 | <h3><a name="re-lc"></a><code>p1 /{l<sub>1</sub>, ..., l<sub>n</sub>} p2</code></h3> | ||
144 | <p> | ||
145 | Syntax of <em>re</em> module. Equivalent to <code>lpeg.Lc(p1, p2, l<sub>1</sub>, ..., l<sub>n</sub>)</code>. | ||
146 | </p> | ||
147 | |||
148 | <p> | ||
149 | The <code>/{}</code> operator is left-associative. | ||
150 | </p> | ||
151 | |||
152 | <p> | ||
153 | A grammar can use both choice operators (<code>/</code> and <code>/{}</code>), | ||
154 | but a single choice can not mix them. That is, the parser | ||
155 | of <code>re</code> module will not recognize a pattern as | ||
156 | <code>p1 / p2 /{l<sub>1</sub>} p3</code>. | ||
157 | </p> | ||
158 | |||
159 | |||
160 | |||
161 | <h2><a name="ex">Some Examples</a></h2> | ||
162 | |||
163 | <h3>Throwing a label</h3> | ||
164 | <p> | ||
165 | The following example defines a grammar that matches | ||
166 | a list of identifiers separated by commas. A label | ||
167 | is thrown when there is an error matching an identifier | ||
168 | or a comma: | ||
169 | </p> | ||
170 | <pre class="example"> | ||
171 | local m = require'lpeglabel' | ||
172 | |||
173 | local g = m.P{ | ||
174 | "S", | ||
175 | S = m.V"Id" * m.V"List", | ||
176 | List = -m.P(1) + ("," + m.T(2)) * m.V"Id" * m.V"List", | ||
177 | Id = m.R'az'^1 + m.T(1), | ||
178 | } | ||
179 | |||
180 | function mymatch (g, s) | ||
181 | local r, e = g:match(s) | ||
182 | if not r then | ||
183 | if e == 1 then | ||
184 | return r, "Error: expecting an identifier" | ||
185 | elseif e == 2 then | ||
186 | return r, "Error: expecting ','" | ||
187 | else | ||
188 | return r, "Error" | ||
189 | end | ||
190 | end | ||
191 | return r | ||
192 | end | ||
193 | |||
194 | print(mymatch(g, "a,b")) | ||
195 | print(mymatch(g, "a b")) | ||
196 | print(mymatch(g, ", b")) | ||
197 | </pre> | ||
198 | <p> | ||
199 | In this example we could think about writing rule <em>List</em> as follows: | ||
200 | <pre class="example"> | ||
201 | List = m.P(("," + m.T(2)) * m.V"Id")^0 | ||
202 | </pre> | ||
203 | but this would give us an expression that when matching | ||
204 | the end of input would result in a failure with a label | ||
205 | different from 0, that is equivalent to the regular failure, | ||
206 | and the result of the repetition would be this label. | ||
207 | </p> | ||
208 | |||
209 | <p> | ||
210 | In the previous example we could have also created a table | ||
211 | with the error messages to improve the readbility of the PEG. | ||
212 | Below we rewrite the grammar following this approach: | ||
213 | </p> | ||
214 | |||
215 | <pre class="example"> | ||
216 | local m = require'lpeglabel' | ||
217 | |||
218 | local errUndef = 0 | ||
219 | local errId = 1 | ||
220 | local errComma = 2 | ||
221 | |||
222 | local terror = { | ||
223 | [errUndef] = "Error", | ||
224 | [errId] = "Error: expecting an identifier", | ||
225 | [errComma] = "Error: expecting ','", | ||
226 | } | ||
227 | |||
228 | local g = m.P{ | ||
229 | "S", | ||
230 | S = m.V"Id" * m.V"List", | ||
231 | List = -m.P(1) + ("," + m.T(errComma)) * m.V"Id" * m.V"List", | ||
232 | Id = m.R'az'^1 + m.T(errId), | ||
233 | } | ||
234 | |||
235 | function mymatch (g, s) | ||
236 | local r, e = g:match(s) | ||
237 | if not r then | ||
238 | return r, terror[e] | ||
239 | end | ||
240 | return r | ||
241 | end | ||
242 | |||
243 | print(mymatch(g, "a,b")) | ||
244 | print(mymatch(g, "a b")) | ||
245 | print(mymatch(g, ", b")) | ||
246 | </pre> | ||
247 | |||
248 | <h3>Throwing a label using the <em>re</em> module</h3> | ||
249 | |||
250 | <p> | ||
251 | We can also rewrite the previous example using the <em>re</em> module | ||
252 | as follows: | ||
253 | </p> | ||
254 | <pre class="example"> | ||
255 | local re = require 're' | ||
256 | |||
257 | local g = re.compile[[ | ||
258 | S <- Id List | ||
259 | List <- !. / (',' / %{2}) Id List | ||
260 | Id <- [a-z] / %{1} | ||
261 | ]] | ||
262 | |||
263 | function mymatch (g, s) | ||
264 | local r, e = g:match(s) | ||
265 | if not r then | ||
266 | if e == 1 then | ||
267 | return r, "Error: expecting an identifier" | ||
268 | elseif e == 2 then | ||
269 | return r, "Error: expecting ','" | ||
270 | else | ||
271 | return r, "Error" | ||
272 | end | ||
273 | end | ||
274 | return r | ||
275 | end | ||
276 | |||
277 | print(mymatch(g, "a,b")) | ||
278 | print(mymatch(g, "a b")) | ||
279 | print(mymatch(g, ", b")) | ||
280 | </pre> | ||
281 | |||
282 | <p> | ||
283 | Another way to describe the previous example using the <em>re</em> module | ||
284 | is by using a table with the description the errors (<em>terror</em>) and | ||
285 | another table that associates a name to a given label (<em>tlabel</em>): | ||
286 | </p> | ||
287 | <pre class="example"> | ||
288 | local re = require 're' | ||
289 | |||
290 | local errUndef, errId, errComma = 0, 1, 2 | ||
291 | |||
292 | local terror = { | ||
293 | [errUndef] = "Error", | ||
294 | [errId] = "Error: expecting an identifier", | ||
295 | [errComma] = "Error: expecting ','", | ||
296 | } | ||
297 | |||
298 | local tlabels = { ["errUndef"] = errUndef, | ||
299 | ["errId"] = errId, | ||
300 | ["errComma"] = errComma } | ||
301 | |||
302 | re.setlabels(tlabels) | ||
303 | |||
304 | local g = re.compile[[ | ||
305 | S <- Id List | ||
306 | List <- !. / (',' / %{errComma}) Id List | ||
307 | Id <- [a-z] / %{errId} | ||
308 | ]] | ||
309 | |||
310 | function mymatch (g, s) | ||
311 | local r, e = g:match(s) | ||
312 | if not r then | ||
313 | return r, terror[e] | ||
314 | end | ||
315 | return r | ||
316 | end | ||
317 | |||
318 | print(mymatch(g, "a,b")) | ||
319 | print(mymatch(g, "a b")) | ||
320 | print(mymatch(g, ", b")) | ||
321 | </pre> | ||
322 | |||
323 | |||
324 | |||
325 | <h3>Throwing and catching a label</h3> | ||
326 | |||
327 | <p> | ||
328 | When a label is thrown, the grammar itself can handle this label | ||
329 | by using the labeled ordered choice. Below we rewrite the example | ||
330 | of the list of identifiers to show this feature: | ||
331 | </p> | ||
332 | <pre class="example"> | ||
333 | local m = require'lpeglabel' | ||
334 | |||
335 | local errUndef, errId, errComma = 0, 1, 2 | ||
336 | |||
337 | local terror = { | ||
338 | [errUndef] = "Error", | ||
339 | [errId] = "Error: expecting an identifier", | ||
340 | [errComma] = "Error: expecting ','", | ||
341 | } | ||
342 | |||
343 | g = m.P{ | ||
344 | "S", | ||
345 | S = m.Lc(m.Lc(m.V"Id" * m.V"List", m.V"ErrId", errId), | ||
346 | m.V"ErrComma", errComma), | ||
347 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", | ||
348 | Id = m.R'az'^1 + m.T(errId), | ||
349 | Comma = "," + m.T(errComma), | ||
350 | ErrId = m.Cc(errId) / terror, | ||
351 | ErrComma = m.Cc(errComma) / terror | ||
352 | } | ||
353 | |||
354 | print(g:match("a,b")) | ||
355 | print(g:match("a b")) | ||
356 | print(g:match(",b")) | ||
357 | </pre> | ||
358 | |||
359 | <p> | ||
360 | As was pointed out <a href="#f-lc">before</a>, the labeled ordered | ||
361 | choice is not associative, so we should impose a left-associative | ||
362 | order when using function <code>Lc</code>. | ||
363 | </p> | ||
364 | <p> | ||
365 | Below we use the <em>re</em> module to throw and catch labels. | ||
366 | As was pointed out <a href="#re-lc">before</a>, the <code>/{}</code> | ||
367 | operator is left-associative, so we do not need to manually impose | ||
368 | a left-associative order as we did in the previous example that | ||
369 | used <code>Lc</code>: | ||
370 | </p> | ||
371 | <pre class="example"> | ||
372 | local re = require're' | ||
373 | |||
374 | local terror = {} | ||
375 | |||
376 | local function newError(l, msg) | ||
377 | table.insert(terror, { l = l, msg = msg } ) | ||
378 | end | ||
379 | |||
380 | newError("errId", "Error: expecting an identifier") | ||
381 | newError("errComma", "Error: expecting ','") | ||
382 | |||
383 | local labelCode = {} | ||
384 | local labelMsg = {} | ||
385 | for k, v in ipairs(terror) do | ||
386 | labelCode[v.l] = k | ||
387 | labelMsg[v.l] = v.msg | ||
388 | end | ||
389 | |||
390 | re.setlabels(labelCode) | ||
391 | |||
392 | local p = re.compile([[ | ||
393 | S <- Id List /{errId} ErrId /{errComma} ErrComma | ||
394 | List <- !. / Comma Id List | ||
395 | Id <- [a-z]+ / %{errId} | ||
396 | Comma <- ',' / %{errComma} | ||
397 | ErrId <- '' -> errId | ||
398 | ErrComma <- '' -> errComma | ||
399 | ]], labelMsg) | ||
400 | |||
401 | print(p:match("a,b")) | ||
402 | print(p:match("a b")) | ||
403 | print(p:match(",b")) | ||
404 | </pre> | ||
405 | |||
406 | |||
407 | <h3>Tiny Language</h3> | ||
408 | <p> | ||
409 | As a more complex example, below we have the grammar | ||
410 | for the Tiny language, as described in | ||
411 | <a href="http://arxiv.org/abs/1405.6646">this</a> paper. | ||
412 | The example below can also how the line where the syntactic | ||
413 | error probably happened. | ||
414 | </p> | ||
415 | <pre class="example"> | ||
416 | local re = require 're' | ||
417 | |||
418 | local terror = {} | ||
419 | |||
420 | local function newError(l, msg) | ||
421 | table.insert(terror, { l = l, msg = msg} ) | ||
422 | end | ||
423 | |||
424 | newError("errSemi", "Error: missing ';'") | ||
425 | newError("errExpIf", "Error: expected expression after 'if'") | ||
426 | newError("errThen", "Error: expected 'then' keyword") | ||
427 | newError("errCmdSeq1", "Error: expected at least a command after 'then'") | ||
428 | newError("errCmdSeq2", "Error: expected at least a command after 'else'") | ||
429 | newError("errEnd", "Error: expected 'end' keyword") | ||
430 | newError("errCmdSeqRep", "Error: expected at least a command after 'repeat'") | ||
431 | newError("errUntil", "Error: expected 'until' keyword") | ||
432 | newError("errExpRep", "Error: expected expression after 'until'") | ||
433 | newError("errAssignOp", "Error: expected ':=' in assigment") | ||
434 | newError("errExpAssign", "Error: expected expression after ':='") | ||
435 | newError("errReadName", "Error: expected an identifier after 'read'") | ||
436 | newError("errWriteExp", "Error: expected expression after 'write'") | ||
437 | newError("errSimpExp", "Error: expected '(', ID, or number after '<' or '='") | ||
438 | newError("errTerm", "Error: expected '(', ID, or number after '+' or '-'") | ||
439 | newError("errFactor", "Error: expected '(', ID, or number after '*' or '/'") | ||
440 | newError("errExpFac", "Error: expected expression after '('") | ||
441 | newError("errClosePar", "Error: expected ')' after expression") | ||
442 | |||
443 | local line | ||
444 | |||
445 | local function incLine() | ||
446 | line = line + 1 | ||
447 | return true | ||
448 | end | ||
449 | |||
450 | local function countLine(s, i) | ||
451 | line = 1 | ||
452 | local p = re.compile([[ | ||
453 | S <- (%nl -> incLine / .)* | ||
454 | ]], { incLine = incLine}) | ||
455 | p:match(s:sub(1, i)) | ||
456 | return true | ||
457 | end | ||
458 | |||
459 | local labelCode = {} | ||
460 | for k, v in ipairs(terror) do | ||
461 | labelCode[v.l] = k | ||
462 | end | ||
463 | |||
464 | re.setlabels(labelCode) | ||
465 | |||
466 | local g = re.compile([[ | ||
467 | Tiny <- CmdSeq | ||
468 | CmdSeq <- (Cmd (SEMICOLON / ErrSemi)) (Cmd (SEMICOLON / ErrSemi))* | ||
469 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd | ||
470 | IfCmd <- IF (Exp / ErrExpIf) (THEN / ErrThen) (CmdSeq / ErrCmdSeq1) (ELSE (CmdSeq / ErrCmdSeq2) / '') (END / ErrEnd) | ||
471 | RepeatCmd <- REPEAT (CmdSeq / ErrCmdSeqRep) (UNTIL / ErrUntil) (Exp / ErrExpRep) | ||
472 | AssignCmd <- NAME (ASSIGNMENT / ErrAssignOp) (Exp / ErrExpAssign) | ||
473 | ReadCmd <- READ (NAME / ErrReadName) | ||
474 | WriteCmd <- WRITE (Exp / ErrWriteExp) | ||
475 | Exp <- SimpleExp ((LESS / EQUAL) (SimpleExp / ErrSimpExp) / '') | ||
476 | SimpleExp <- Term ((ADD / SUB) (Term / ErrTerm))* | ||
477 | Term <- Factor ((MUL / DIV) (Factor / ErrFactor))* | ||
478 | Factor <- OPENPAR (Exp / ErrExpFac) (CLOSEPAR / ErrClosePar) / NUMBER / NAME | ||
479 | ErrSemi <- ErrCount %{errSemi} | ||
480 | ErrExpIf <- ErrCount %{errExpIf} | ||
481 | ErrThen <- ErrCount %{errThen} | ||
482 | ErrCmdSeq1 <- ErrCount %{errCmdSeq1} | ||
483 | ErrCmdSeq2 <- ErrCount %{errCmdSeq2} | ||
484 | ErrEnd <- ErrCount %{errEnd} | ||
485 | ErrCmdSeqRep <- ErrCount %{errCmdSeqRep} | ||
486 | ErrUntil <- ErrCount %{errUntil} | ||
487 | ErrExpRep <- ErrCount %{errExpRep} | ||
488 | ErrAssignOp <- ErrCount %{errAssignOp} | ||
489 | ErrExpAssign <- ErrCount %{errExpAssign} | ||
490 | ErrReadName <- ErrCount %{errReadName} | ||
491 | ErrWriteExp <- ErrCount %{errWriteExp} | ||
492 | ErrSimpExp <- ErrCount %{errSimpExp} | ||
493 | ErrTerm <- ErrCount %{errTerm} | ||
494 | ErrFactor <- ErrCount %{errFactor} | ||
495 | ErrExpFac <- ErrCount %{errExpFac} | ||
496 | ErrClosePar <- ErrCount %{errClosePar} | ||
497 | ErrCount <- '' => countLine | ||
498 | ADD <- Sp '+' | ||
499 | ASSIGNMENT <- Sp ':=' | ||
500 | CLOSEPAR <- Sp ')' | ||
501 | DIV <- Sp '/' | ||
502 | IF <- Sp 'if' | ||
503 | ELSE <- Sp 'else' | ||
504 | END <- Sp 'end' | ||
505 | EQUAL <- Sp '=' | ||
506 | LESS <- Sp '<' | ||
507 | MUL <- Sp '*' | ||
508 | NAME <- Sp !RESERVED [a-z]+ | ||
509 | NUMBER <- Sp [0-9]+ | ||
510 | OPENPAR <- Sp '(' | ||
511 | READ <- Sp 'read' | ||
512 | REPEAT <- Sp 'repeat' | ||
513 | SEMICOLON <- Sp ';' | ||
514 | SUB <- Sp '-' | ||
515 | THEN <- Sp 'then' | ||
516 | UNTIL <- Sp 'until' | ||
517 | WRITE <- Sp 'write' | ||
518 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | ||
519 | Sp <- %s* | ||
520 | ]], { countLine = countLine }) | ||
521 | </pre> | ||
522 | |||
523 | |||
524 | <h2><a name="download"></a>Download</h2> | ||
525 | |||
526 | <p>LPeg | ||
527 | <a href="http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-0.12.tar.gz">source code</a>.</p> | ||
528 | |||
529 | |||
530 | <h2><a name="license">License</a></h2> | ||
531 | |||
532 | <p> | ||
533 | The MIT License (MIT) | ||
534 | </p> | ||
535 | <p> | ||
536 | Copyright (c) 2014-2015 Sérgio Medeiros | ||
537 | </p> | ||
538 | <p> | ||
539 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
540 | of this software and associated documentation files (the "Software"), to deal | ||
541 | in the Software without restriction, including without limitation the rights | ||
542 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
543 | copies of the Software, and to permit persons to whom the Software is | ||
544 | furnished to do so, subject to the following conditions: | ||
545 | </p> | ||
546 | <p> | ||
547 | The above copyright notice and this permission notice shall be included in all | ||
548 | copies or substantial portions of the Software. | ||
549 | </p> | ||
550 | <p> | ||
551 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
552 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
553 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
554 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
555 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
556 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
557 | SOFTWARE. | ||
558 | |||
559 | |||
560 | |||
561 | |||
562 | </p> | ||
563 | |||
564 | </div> <!-- id="content" --> | ||
565 | |||
566 | </div> <!-- id="main" --> | ||
567 | |||
568 | <div id="about"> | ||
569 | </div> <!-- id="about" --> | ||
570 | |||
571 | </div> <!-- id="container" --> | ||
572 | |||
573 | </body> | ||
574 | </html> | ||