diff options
-rw-r--r-- | examples/listIdCatch.lua | 28 | ||||
-rw-r--r-- | examples/listIdCatchRe.lua | 34 | ||||
-rw-r--r-- | examples/recovery.lua | 2 | ||||
-rw-r--r-- | examples/recoveryFabio.lua | 119 | ||||
-rw-r--r-- | examples/recoveryOpFail.lua | 2 | ||||
-rw-r--r-- | examples/tiny.lua | 84 |
6 files changed, 157 insertions, 112 deletions
diff --git a/examples/listIdCatch.lua b/examples/listIdCatch.lua deleted file mode 100644 index 5ad6f2d..0000000 --- a/examples/listIdCatch.lua +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | local m = require'lpeglabel' | ||
2 | |||
3 | local terror = {} | ||
4 | |||
5 | local function newError(s) | ||
6 | table.insert(terror, s) | ||
7 | return #terror | ||
8 | end | ||
9 | |||
10 | local errUndef = newError("undefined") | ||
11 | local errId = newError("expecting an identifier") | ||
12 | local errComma = newError("expecting ','") | ||
13 | |||
14 | local g = m.P{ | ||
15 | "S", | ||
16 | S = m.Lc(m.Lc(m.V"Id" * m.V"List", m.V"ErrId", errId), | ||
17 | m.V"ErrComma", errComma), | ||
18 | List = -m.P(1) + (m.V"Comma" + m.T(errComma)) * (m.V"Id" + m.T(errId)) * m.V"List", | ||
19 | Id = m.V"Sp" * m.R'az'^1, | ||
20 | Comma = m.V"Sp" * ",", | ||
21 | Sp = m.S" \n\t"^0, | ||
22 | ErrId = m.Cc(errId) / terror, | ||
23 | ErrComma = m.Cc(errComma) / terror | ||
24 | } | ||
25 | |||
26 | print(m.match(g, "one,two")) | ||
27 | print(m.match(g, "one two")) | ||
28 | print(m.match(g, "one,\n two,\nthree,")) | ||
diff --git a/examples/listIdCatchRe.lua b/examples/listIdCatchRe.lua deleted file mode 100644 index 8971191..0000000 --- a/examples/listIdCatchRe.lua +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | local re = require'relabel' | ||
2 | |||
3 | local terror = {} | ||
4 | |||
5 | local function newError(l, msg) | ||
6 | table.insert(terror, { l = l, msg = msg } ) | ||
7 | end | ||
8 | |||
9 | newError("errId", "Error: expecting an identifier") | ||
10 | newError("errComma", "Error: expecting ','") | ||
11 | |||
12 | local labelCode = {} | ||
13 | local labelMsg = {} | ||
14 | for k, v in ipairs(terror) do | ||
15 | labelCode[v.l] = k | ||
16 | labelMsg[v.l] = v.msg | ||
17 | end | ||
18 | |||
19 | re.setlabels(labelCode) | ||
20 | |||
21 | local p = re.compile([[ | ||
22 | S <- Id List /{errId} ErrId /{errComma} ErrComma | ||
23 | List <- !. / Comma Id List | ||
24 | Id <- [a-z]+ / %{errId} | ||
25 | Comma <- ',' / %{errComma} | ||
26 | ErrId <- '' -> errId | ||
27 | ErrComma <- '' -> errComma | ||
28 | ]], labelMsg) | ||
29 | |||
30 | print(p:match("a,b")) | ||
31 | print(p:match("a b")) | ||
32 | print(p:match(",b")) | ||
33 | |||
34 | |||
diff --git a/examples/recovery.lua b/examples/recovery.lua index 3272ae7..bb17b54 100644 --- a/examples/recovery.lua +++ b/examples/recovery.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local lpeg = require"lpeglabel" | 1 | local lpeg = require"lpeglabelrec" |
2 | 2 | ||
3 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V | 3 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V |
4 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt | 4 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt |
diff --git a/examples/recoveryFabio.lua b/examples/recoveryFabio.lua new file mode 100644 index 0000000..f16c9e7 --- /dev/null +++ b/examples/recoveryFabio.lua | |||
@@ -0,0 +1,119 @@ | |||
1 | local lpeg = require"lpeglabelrec" | ||
2 | |||
3 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V | ||
4 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt | ||
5 | local T, Rec = lpeg.T, lpeg.Rec | ||
6 | |||
7 | local labels = { | ||
8 | {"NoExp", "no expression found"}, | ||
9 | {"Extra", "extra characters found after the expression"}, | ||
10 | {"ExpTerm", "expected a term after the operator"}, | ||
11 | {"ExpExp", "expected an expression after the parenthesis"}, | ||
12 | {"MisClose", "missing a closing ')' after the expression"}, | ||
13 | } | ||
14 | |||
15 | local function labelindex(labname) | ||
16 | for i, elem in ipairs(labels) do | ||
17 | if elem[1] == labname then | ||
18 | return i | ||
19 | end | ||
20 | end | ||
21 | error("could not find label: " .. labname) | ||
22 | end | ||
23 | |||
24 | local errors = {} | ||
25 | |||
26 | local function expect(patt, labname, recpatt) | ||
27 | local i = labelindex(labname) | ||
28 | function recorderror(input, pos) | ||
29 | table.insert(errors, {i, pos}) | ||
30 | return true | ||
31 | end | ||
32 | return patt + T(i) | ||
33 | end | ||
34 | |||
35 | local num = R("09")^1 / tonumber | ||
36 | local op = S("+-") | ||
37 | |||
38 | local function compute(tokens) | ||
39 | local result = tokens[1] | ||
40 | for i = 2, #tokens, 2 do | ||
41 | if tokens[i] == '+' then | ||
42 | result = result + tokens[i+1] | ||
43 | elseif tokens[i] == '-' then | ||
44 | result = result - tokens[i+1] | ||
45 | else | ||
46 | error('unknown operation: ' .. tokens[i]) | ||
47 | end | ||
48 | end | ||
49 | return result | ||
50 | end | ||
51 | |||
52 | local g = P { | ||
53 | "Exp", | ||
54 | Exp = Ct(V"Operand" * (C(op) * V"Operand")^0) / compute, | ||
55 | Operand = expect(V"Term", "ExpTerm"), | ||
56 | Term = num + V"Group", | ||
57 | Group = "(" * V"InnerExp" * expect(")", "MisClose", ""); | ||
58 | InnerExp = expect(V"Exp", "ExpExp", (P(1) - ")")^0 * Cc(0)); | ||
59 | |||
60 | } | ||
61 | |||
62 | local subject, errors | ||
63 | |||
64 | function recorderror(pos, lab) | ||
65 | local line, col = re.calcline(subject, pos) | ||
66 | table.insert(errors, { line = line, col = col, msg = terror[lab] }) | ||
67 | end | ||
68 | |||
69 | function record (labname) | ||
70 | return (m.Cp() * m.Cc(labelindex(labname))) / recorderror | ||
71 | end | ||
72 | |||
73 | function sync (p) | ||
74 | return (-p * m.P(1))^0 | ||
75 | end | ||
76 | |||
77 | function defaultValue () | ||
78 | return m.Cc"NONE" | ||
79 | end | ||
80 | |||
81 | local recg = P { | ||
82 | "S", | ||
83 | S = Rec(m.V"A", Cc(0), labelindex("ExpTerm")), -- default value is 0 | ||
84 | A = Rec(m.V"B", Cc(0), labelindex("ExpExp")), | ||
85 | B = Rec(m.V"Sg", Cc(0), labelindex("InnerExp")), | ||
86 | Sg = Rec(g, Cc(0), labelindex("MisClose")), | ||
87 | ErrExpTerm = record(labelindex("ExpTerm")) * sync() * defaultValue() | ||
88 | } | ||
89 | |||
90 | |||
91 | local function eval(input) | ||
92 | local result, label, suffix = recg:match(input) | ||
93 | if #errors == 0 then | ||
94 | return result | ||
95 | else | ||
96 | local out = {} | ||
97 | for i, err in ipairs(errors) do | ||
98 | local pos = err[2] | ||
99 | local msg = labels[err[1]][2] | ||
100 | table.insert(out, "syntax error: " .. msg .. " (at index " .. pos .. ")") | ||
101 | end | ||
102 | errors = {} | ||
103 | return nil, table.concat(out, "\n") | ||
104 | end | ||
105 | end | ||
106 | |||
107 | print(eval "90-70*5") | ||
108 | --> 20 | ||
109 | |||
110 | print(eval "2+") | ||
111 | --> 2 + 0 | ||
112 | |||
113 | print(eval "-2") | ||
114 | --> 0 - 2 | ||
115 | |||
116 | |||
117 | print(eval "1+3+-9") | ||
118 | --> 1 + 3 + 0 - 9 | ||
119 | |||
diff --git a/examples/recoveryOpFail.lua b/examples/recoveryOpFail.lua index d65b9e0..bd1beb7 100644 --- a/examples/recoveryOpFail.lua +++ b/examples/recoveryOpFail.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local lpeg = require"lpeglabel" | 1 | local lpeg = require"lpeglabelrec" |
2 | 2 | ||
3 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V | 3 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V |
4 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt | 4 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt |
diff --git a/examples/tiny.lua b/examples/tiny.lua index 99c3144..784e031 100644 --- a/examples/tiny.lua +++ b/examples/tiny.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local re = require 'relabel' | 1 | local re = require 'relabelrec' |
2 | 2 | ||
3 | local terror = {} | 3 | local terror = {} |
4 | 4 | ||
@@ -25,21 +25,6 @@ newError("errFactor", "Error: expected '(', ID, or number after '*' or '/'") | |||
25 | newError("errExpFac", "Error: expected expression after '('") | 25 | newError("errExpFac", "Error: expected expression after '('") |
26 | newError("errClosePar", "Error: expected ')' after expression") | 26 | newError("errClosePar", "Error: expected ')' after expression") |
27 | 27 | ||
28 | local line | ||
29 | |||
30 | local function incLine() | ||
31 | line = line + 1 | ||
32 | return true | ||
33 | end | ||
34 | |||
35 | local function countLine(s, i) | ||
36 | line = 1 | ||
37 | local p = re.compile([[ | ||
38 | S <- (%nl -> incLine / .)* | ||
39 | ]], { incLine = incLine}) | ||
40 | p:match(s:sub(1, i)) | ||
41 | return true | ||
42 | end | ||
43 | 28 | ||
44 | local labelCode = {} | 29 | local labelCode = {} |
45 | for k, v in ipairs(terror) do | 30 | for k, v in ipairs(terror) do |
@@ -48,7 +33,7 @@ end | |||
48 | 33 | ||
49 | re.setlabels(labelCode) | 34 | re.setlabels(labelCode) |
50 | 35 | ||
51 | local g = re.compile([[ | 36 | local g = re.compile[[ |
52 | Tiny <- CmdSeq | 37 | Tiny <- CmdSeq |
53 | CmdSeq <- (Cmd (SEMICOLON / ErrSemi)) (Cmd (SEMICOLON / ErrSemi))* | 38 | CmdSeq <- (Cmd (SEMICOLON / ErrSemi)) (Cmd (SEMICOLON / ErrSemi))* |
54 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd | 39 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd |
@@ -61,25 +46,24 @@ local g = re.compile([[ | |||
61 | SimpleExp <- Term ((ADD / SUB) (Term / ErrTerm))* | 46 | SimpleExp <- Term ((ADD / SUB) (Term / ErrTerm))* |
62 | Term <- Factor ((MUL / DIV) (Factor / ErrFactor))* | 47 | Term <- Factor ((MUL / DIV) (Factor / ErrFactor))* |
63 | Factor <- OPENPAR (Exp / ErrExpFac) (CLOSEPAR / ErrClosePar) / NUMBER / NAME | 48 | Factor <- OPENPAR (Exp / ErrExpFac) (CLOSEPAR / ErrClosePar) / NUMBER / NAME |
64 | ErrSemi <- ErrCount %{errSemi} | 49 | ErrSemi <- %{errSemi} |
65 | ErrExpIf <- ErrCount %{errExpIf} | 50 | ErrExpIf <- %{errExpIf} |
66 | ErrThen <- ErrCount %{errThen} | 51 | ErrThen <- %{errThen} |
67 | ErrCmdSeq1 <- ErrCount %{errCmdSeq1} | 52 | ErrCmdSeq1 <- %{errCmdSeq1} |
68 | ErrCmdSeq2 <- ErrCount %{errCmdSeq2} | 53 | ErrCmdSeq2 <- %{errCmdSeq2} |
69 | ErrEnd <- ErrCount %{errEnd} | 54 | ErrEnd <- %{errEnd} |
70 | ErrCmdSeqRep <- ErrCount %{errCmdSeqRep} | 55 | ErrCmdSeqRep <- %{errCmdSeqRep} |
71 | ErrUntil <- ErrCount %{errUntil} | 56 | ErrUntil <- %{errUntil} |
72 | ErrExpRep <- ErrCount %{errExpRep} | 57 | ErrExpRep <- %{errExpRep} |
73 | ErrAssignOp <- ErrCount %{errAssignOp} | 58 | ErrAssignOp <- %{errAssignOp} |
74 | ErrExpAssign <- ErrCount %{errExpAssign} | 59 | ErrExpAssign <- %{errExpAssign} |
75 | ErrReadName <- ErrCount %{errReadName} | 60 | ErrReadName <- %{errReadName} |
76 | ErrWriteExp <- ErrCount %{errWriteExp} | 61 | ErrWriteExp <- %{errWriteExp} |
77 | ErrSimpExp <- ErrCount %{errSimpExp} | 62 | ErrSimpExp <- %{errSimpExp} |
78 | ErrTerm <- ErrCount %{errTerm} | 63 | ErrTerm <- %{errTerm} |
79 | ErrFactor <- ErrCount %{errFactor} | 64 | ErrFactor <- %{errFactor} |
80 | ErrExpFac <- ErrCount %{errExpFac} | 65 | ErrExpFac <- %{errExpFac} |
81 | ErrClosePar <- ErrCount %{errClosePar} | 66 | ErrClosePar <- %{errClosePar} |
82 | ErrCount <- '' => countLine | ||
83 | ADD <- Sp '+' | 67 | ADD <- Sp '+' |
84 | ASSIGNMENT <- Sp ':=' | 68 | ASSIGNMENT <- Sp ':=' |
85 | CLOSEPAR <- Sp ')' | 69 | CLOSEPAR <- Sp ')' |
@@ -102,12 +86,17 @@ local g = re.compile([[ | |||
102 | WRITE <- Sp 'write' | 86 | WRITE <- Sp 'write' |
103 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | 87 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ |
104 | Sp <- %s* | 88 | Sp <- %s* |
105 | ]], { countLine = countLine }) | 89 | ]] |
106 | 90 | ||
107 | 91 | ||
108 | local function printError(n, e) | 92 | local function mymatch(g, s) |
109 | assert(n == nil) | 93 | local r, e, sfail = g:match(s) |
110 | print("Line " .. line .. ": " .. terror[e].msg) | 94 | if not r then |
95 | local line, col = re.calcline(s, #s - #sfail) | ||
96 | local msg = "Error at line " .. line .. " (col " .. col .. "): " | ||
97 | return r, msg .. terror[e].msg | ||
98 | end | ||
99 | return r | ||
111 | end | 100 | end |
112 | 101 | ||
113 | local s = [[ | 102 | local s = [[ |
@@ -118,7 +107,7 @@ repeat | |||
118 | n := n - 1 | 107 | n := n - 1 |
119 | until (n < 1); | 108 | until (n < 1); |
120 | write f;]] | 109 | write f;]] |
121 | printError(g:match(s)) | 110 | print(mymatch(g, s)) |
122 | 111 | ||
123 | s = [[ | 112 | s = [[ |
124 | n := 5; | 113 | n := 5; |
@@ -128,14 +117,14 @@ repeat | |||
128 | n := n - 1; | 117 | n := n - 1; |
129 | until (n < 1); | 118 | until (n < 1); |
130 | read ;]] | 119 | read ;]] |
131 | printError(g:match(s)) | 120 | print(mymatch(g, s)) |
132 | 121 | ||
133 | s = [[ | 122 | s = [[ |
134 | if a < 1 then | 123 | if a < 1 then |
135 | b := 2; | 124 | b := 2; |
136 | else | 125 | else |
137 | b := 3;]] | 126 | b := 3;]] |
138 | printError(g:match(s)) | 127 | print(mymatch(g, s)) |
139 | 128 | ||
140 | s = [[ | 129 | s = [[ |
141 | n := 5; | 130 | n := 5; |
@@ -145,7 +134,7 @@ repeat | |||
145 | n := n - 1; | 134 | n := n - 1; |
146 | untill (n < 1); | 135 | untill (n < 1); |
147 | ]] | 136 | ]] |
148 | printError(g:match(s)) | 137 | print(mymatch(g, s)) |
149 | 138 | ||
150 | s = [[ | 139 | s = [[ |
151 | n := 5; | 140 | n := 5; |
@@ -155,9 +144,8 @@ repeat | |||
155 | n := n - 1; | 144 | n := n - 1; |
156 | 3 (n < 1); | 145 | 3 (n < 1); |
157 | ]] | 146 | ]] |
158 | printError(g:match(s)) | 147 | print(mymatch(g, s)) |
159 | |||
160 | printError(g:match("a : 2")) | ||
161 | printError(g:match("a := (2")) | ||
162 | 148 | ||
149 | print(mymatch(g, "a : 2")) | ||
150 | print(mymatch(g, "a := (2")) | ||
163 | 151 | ||