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