diff options
author | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-28 14:29:49 -0300 |
---|---|---|
committer | Sérgio Queiroz <sqmedeiros@gmail.com> | 2017-12-28 14:29:49 -0300 |
commit | 59da25ff241a83d8139e41199ef7a23f6e17fa65 (patch) | |
tree | a9ad13fa0f8ddb50855b716b349e4ded5d5fac8d | |
parent | 772df00e061db3cd7d0af92c8ab65bc023d8121d (diff) | |
download | lpeglabel-59da25ff241a83d8139e41199ef7a23f6e17fa65.tar.gz lpeglabel-59da25ff241a83d8139e41199ef7a23f6e17fa65.tar.bz2 lpeglabel-59da25ff241a83d8139e41199ef7a23f6e17fa65.zip |
Updating examples to the new semantics
-rw-r--r-- | examples/exp.lua | 100 | ||||
-rw-r--r-- | examples/expRec.lua | 58 | ||||
-rw-r--r-- | examples/expRecAut.lua | 37 | ||||
-rw-r--r-- | examples/farthest.lua | 16 | ||||
-rw-r--r-- | examples/listId1.lua | 8 | ||||
-rw-r--r-- | examples/listId2.lua | 19 | ||||
-rw-r--r-- | examples/listId2Rec2.lua | 52 | ||||
-rw-r--r-- | examples/listId2Rec2Cap.lua | 45 | ||||
-rw-r--r-- | examples/listIdRe1.lua | 8 | ||||
-rw-r--r-- | examples/listIdRe2.lua | 53 | ||||
-rw-r--r-- | examples/tiny.lua | 147 | ||||
-rw-r--r-- | lpvm.c | 4 |
12 files changed, 278 insertions, 269 deletions
diff --git a/examples/exp.lua b/examples/exp.lua new file mode 100644 index 0000000..4afe83e --- /dev/null +++ b/examples/exp.lua | |||
@@ -0,0 +1,100 @@ | |||
1 | -- Matthew's recovery example | ||
2 | lpeg = require'lpeglabel' | ||
3 | |||
4 | local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V | ||
5 | local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt | ||
6 | local T = lpeg.T | ||
7 | |||
8 | local labels = { | ||
9 | NoExp = "no expression found", | ||
10 | Extra = "extra characters found after the expression", | ||
11 | ExpTerm = "expected a term after the operator", | ||
12 | ExpExp = "expected an expression after the parenthesis", | ||
13 | MisClose = "missing a closing ')' after the expression", | ||
14 | } | ||
15 | |||
16 | local errors = {} | ||
17 | |||
18 | local function expect(patt, labname) | ||
19 | function recorderror(input, pos) | ||
20 | table.insert(errors, {labname, pos}) | ||
21 | return true | ||
22 | end | ||
23 | return patt + Cmt("", recorderror) * T(labname) | ||
24 | end | ||
25 | |||
26 | local num = R("09")^1 / tonumber | ||
27 | local op = S("+-*/") | ||
28 | |||
29 | local function compute(tokens) | ||
30 | local result = tokens[1] | ||
31 | for i = 2, #tokens, 2 do | ||
32 | if tokens[i] == '+' then | ||
33 | result = result + tokens[i+1] | ||
34 | elseif tokens[i] == '-' then | ||
35 | result = result - tokens[i+1] | ||
36 | elseif tokens[i] == '*' then | ||
37 | result = result * tokens[i+1] | ||
38 | elseif tokens[i] == '/' then | ||
39 | result = result / tokens[i+1] | ||
40 | else | ||
41 | error('unknown operation: ' .. tokens[i]) | ||
42 | end | ||
43 | end | ||
44 | return result | ||
45 | end | ||
46 | |||
47 | local g = P { | ||
48 | "Exp", | ||
49 | Exp = Ct(V"Term" * (C(op) * V"Operand")^0) / compute; | ||
50 | Operand = expect(V"Term", "ExpTerm"); | ||
51 | Term = num + V"Group"; | ||
52 | Group = "(" * V"InnerExp" * expect(")", "MisClose"); | ||
53 | InnerExp = expect(V"Exp", "ExpExp"); | ||
54 | ExpTerm = Cc(0); | ||
55 | MisClose = P""; | ||
56 | ExpExp = (P(1) - ")")^0 * Cc(0); | ||
57 | } | ||
58 | |||
59 | g = expect(g, "NoExp") * expect(-P(1), "Extra") | ||
60 | |||
61 | local function eval(input) | ||
62 | local result, label, suffix = g:match(input) | ||
63 | if #errors == 0 then | ||
64 | return result | ||
65 | else | ||
66 | local out = {} | ||
67 | for i, err in ipairs(errors) do | ||
68 | local pos = err[2] | ||
69 | local msg = labels[err[1]] | ||
70 | table.insert(out, "syntax error: " .. msg .. " (at index " .. pos .. ")") | ||
71 | end | ||
72 | errors = {} | ||
73 | return nil, table.concat(out, "\n") | ||
74 | end | ||
75 | end | ||
76 | |||
77 | assert(eval "98-76*(54/32)" == 37.125) | ||
78 | --> 37.125 | ||
79 | |||
80 | local e, msg = eval "(1+1-1*2/2" | ||
81 | assert(e == nil and msg == "syntax error: missing a closing ')' after the expression (at index 11)") | ||
82 | |||
83 | e, msg = eval "(1+)-1*(2/2)" | ||
84 | assert(e == nil and msg == "syntax error: expected a term after the operator (at index 4)") | ||
85 | |||
86 | e, msg = eval "(1+1)-1*(/2)" | ||
87 | assert(e == nil and msg == "syntax error: expected an expression after the parenthesis (at index 10)") | ||
88 | |||
89 | e, msg = eval "1+(1-(1*2))/2x" | ||
90 | assert(e == nil and msg == "syntax error: extra characters found after the expression (at index 14)") | ||
91 | |||
92 | e, msg = eval "-1+(1-(1*2))/2" | ||
93 | assert(e == nil and msg == "syntax error: no expression found (at index 1)") | ||
94 | |||
95 | e, msg = eval "(1+1-1*(2/2+)-():" | ||
96 | assert(e == nil and msg == "syntax error: expected a term after the operator (at index 13)\n" .. | ||
97 | "syntax error: expected an expression after the parenthesis (at index 16)\n" .. | ||
98 | "syntax error: missing a closing ')' after the expression (at index 17)\n" .. | ||
99 | "syntax error: extra characters found after the expression (at index 17)") | ||
100 | |||
diff --git a/examples/expRec.lua b/examples/expRec.lua index 52bd40a..d111ab0 100644 --- a/examples/expRec.lua +++ b/examples/expRec.lua | |||
@@ -2,28 +2,17 @@ local m = require"lpeglabel" | |||
2 | local re = require"relabel" | 2 | local re = require"relabel" |
3 | 3 | ||
4 | local labels = { | 4 | local labels = { |
5 | {"ExpTermFirst", "expected an expression"}, | 5 | ExpTermFirst = "expected an expression", |
6 | {"ExpTermOp", "expected a term after the operator"}, | 6 | ExpTermOp = "expected a term after the operator", |
7 | {"MisClose", "missing a closing ')' after the expression"}, | 7 | MisClose = "missing a closing ')' after the expression", |
8 | } | 8 | } |
9 | 9 | ||
10 | local function labelindex(labname) | ||
11 | for i, elem in ipairs(labels) do | ||
12 | if elem[1] == labname then | ||
13 | return i | ||
14 | end | ||
15 | end | ||
16 | error("could not find label: " .. labname) | ||
17 | end | ||
18 | |||
19 | local errors, subject | 10 | local errors, subject |
20 | 11 | ||
21 | local function expect(patt, labname) | 12 | local function expect(patt, lab) |
22 | local i = labelindex(labname) | 13 | return patt + m.T(lab) |
23 | return patt + m.T(i) | ||
24 | end | 14 | end |
25 | 15 | ||
26 | |||
27 | local num = m.R("09")^1 / tonumber | 16 | local num = m.R("09")^1 / tonumber |
28 | local op = m.S("+-") | 17 | local op = m.S("+-") |
29 | 18 | ||
@@ -41,22 +30,13 @@ local function compute(tokens) | |||
41 | return result | 30 | return result |
42 | end | 31 | end |
43 | 32 | ||
44 | local g = m.P { | ||
45 | "Exp", | ||
46 | Exp = m.Ct(m.V"OperandFirst" * (m.C(op) * m.V"Operand")^0) / compute, | ||
47 | OperandFirst = expect(m.V"Term", "ExpTermFirst"), | ||
48 | Operand = expect(m.V"Term", "ExpTermOp"), | ||
49 | Term = num + m.V"Group", | ||
50 | Group = "(" * m.V"Exp" * expect(")", "MisClose"), | ||
51 | } | ||
52 | |||
53 | function recorderror(pos, lab) | 33 | function recorderror(pos, lab) |
54 | local line, col = re.calcline(subject, pos) | 34 | local line, col = re.calcline(subject, pos) |
55 | table.insert(errors, { line = line, col = col, msg = labels[lab][2] }) | 35 | table.insert(errors, { line = line, col = col, msg = labels[lab] }) |
56 | end | 36 | end |
57 | 37 | ||
58 | function record (labname) | 38 | function record (lab) |
59 | return (m.Cp() * m.Cc(labelindex(labname))) / recorderror | 39 | return (m.Cp() * m.Cc(lab)) / recorderror |
60 | end | 40 | end |
61 | 41 | ||
62 | function sync (p) | 42 | function sync (p) |
@@ -67,21 +47,23 @@ function defaultValue (p) | |||
67 | return p or m.Cc(1000) | 47 | return p or m.Cc(1000) |
68 | end | 48 | end |
69 | 49 | ||
70 | local grec = m.P { | 50 | local g = m.P { |
71 | "S", | 51 | "Exp", |
72 | S = m.Rec(m.V"A", m.V"ErrExpTermFirst", labelindex("ExpTermFirst")), -- default value is 0 | 52 | Exp = m.Ct(m.V"OperandFirst" * (m.C(op) * m.V"Operand")^0) / compute, |
73 | A = m.Rec(m.V"Sg", m.V"ErrExpTermOp", labelindex("ExpTermOp")), | 53 | OperandFirst = expect(m.V"Term", "ExpTermFirst"), |
74 | Sg = m.Rec(g, m.V"ErrMisClose", labelindex("MisClose")), | 54 | Operand = expect(m.V"Term", "ExpTermOp"), |
75 | ErrExpTermFirst = record("ExpTermFirst") * sync(op + ")") * defaultValue(), | 55 | Term = num + m.V"Group", |
76 | ErrExpTermOp = record("ExpTermOp") * sync(op + ")") * defaultValue(), | 56 | Group = "(" * m.V"Exp" * expect(")", "MisClose"), |
77 | ErrMisClose = record("MisClose") * sync(m.P")") * defaultValue(m.P""), | 57 | ExpTermFirst = record("ExpTermFirst") * sync(op + ")") * defaultValue(), |
58 | ExpTermOp = record("ExpTermOp") * sync(op + ")") * defaultValue(), | ||
59 | MisClose = record("MisClose") * sync(m.P")") * defaultValue(m.P""), | ||
78 | } | 60 | } |
79 | 61 | ||
80 | local function eval(input) | 62 | local function eval(input) |
81 | errors = {} | 63 | errors = {} |
82 | io.write("Input: ", input, "\n") | 64 | io.write("Input: ", input, "\n") |
83 | subject = input | 65 | subject = input |
84 | local result, label, suffix = grec:match(input) | 66 | local result, label, suffix = g:match(input) |
85 | io.write("Syntactic errors found: " .. #errors, "\n") | 67 | io.write("Syntactic errors found: " .. #errors, "\n") |
86 | if #errors > 0 then | 68 | if #errors > 0 then |
87 | local out = {} | 69 | local out = {} |
diff --git a/examples/expRecAut.lua b/examples/expRecAut.lua index b8280a7..18d7606 100644 --- a/examples/expRecAut.lua +++ b/examples/expRecAut.lua | |||
@@ -5,13 +5,11 @@ local num = m.R("09")^1 / tonumber | |||
5 | local op = m.S("+-") | 5 | local op = m.S("+-") |
6 | 6 | ||
7 | local labels = {} | 7 | local labels = {} |
8 | local nlabels = 0 | ||
9 | 8 | ||
10 | local function newError(lab, msg, psync, pcap) | 9 | local function newError(lab, msg, psync, pcap) |
11 | nlabels = nlabels + 1 | ||
12 | psync = psync or m.P(-1) | 10 | psync = psync or m.P(-1) |
13 | pcap = pcap or m.P"" | 11 | pcap = pcap or m.P"" |
14 | labels[lab] = { id = nlabels, msg = msg, psync = psync, pcap = pcap } | 12 | labels[lab] = { msg = msg, psync = psync, pcap = pcap } |
15 | end | 13 | end |
16 | 14 | ||
17 | newError("ExpTermFirst", "expected an expression", op + ")", m.Cc(1000)) | 15 | newError("ExpTermFirst", "expected an expression", op + ")", m.Cc(1000)) |
@@ -21,9 +19,8 @@ newError("Extra", "extra characters found after the expression") | |||
21 | 19 | ||
22 | local errors, subject | 20 | local errors, subject |
23 | 21 | ||
24 | local function expect(patt, labname) | 22 | local function expect(patt, lab) |
25 | local i = labels[labname].id | 23 | return patt + m.T(lab) |
26 | return patt + m.T(i) | ||
27 | end | 24 | end |
28 | 25 | ||
29 | local function compute(tokens) | 26 | local function compute(tokens) |
@@ -40,15 +37,6 @@ local function compute(tokens) | |||
40 | return result | 37 | return result |
41 | end | 38 | end |
42 | 39 | ||
43 | local g = m.P { | ||
44 | "Exp", | ||
45 | Exp = m.Ct(m.V"OperandFirst" * (m.C(op) * m.V"Operand")^0) / compute, | ||
46 | OperandFirst = expect(m.V"Term", "ExpTermFirst"), | ||
47 | Operand = expect(m.V"Term", "ExpTermOp"), | ||
48 | Term = num + m.V"Group", | ||
49 | Group = "(" * m.V"Exp" * expect(")", "MisClose"), | ||
50 | } | ||
51 | |||
52 | function recorderror(pos, lab) | 40 | function recorderror(pos, lab) |
53 | local line, col = re.calcline(subject, pos) | 41 | local line, col = re.calcline(subject, pos) |
54 | table.insert(errors, { line = line, col = col, msg = labels[lab].msg }) | 42 | table.insert(errors, { line = line, col = col, msg = labels[lab].msg }) |
@@ -66,16 +54,29 @@ function defaultValue (p) | |||
66 | return p or m.Cc(1000) | 54 | return p or m.Cc(1000) |
67 | end | 55 | end |
68 | 56 | ||
69 | local grec = g * expect(m.P(-1), "Extra") | 57 | local g = { |
58 | "Exp", | ||
59 | Exp = m.Ct(m.V"OperandFirst" * (m.C(op) * m.V"Operand")^0) / compute, | ||
60 | OperandFirst = expect(m.V"Term", "ExpTermFirst"), | ||
61 | Operand = expect(m.V"Term", "ExpTermOp"), | ||
62 | Term = num + m.V"Group", | ||
63 | Group = "(" * m.V"Exp" * expect(")", "MisClose"), | ||
64 | } | ||
65 | |||
66 | -- set first rule | ||
67 | g[1] = "S" | ||
68 | g["S"] = g["Exp"] * expect(m.P(-1), "Extra") | ||
70 | for k, v in pairs(labels) do | 69 | for k, v in pairs(labels) do |
71 | grec = m.Rec(grec, record(k) * sync(v.psync) * v.pcap, v.id) | 70 | g[k] = record(k) * sync(v.psync) * v.pcap |
72 | end | 71 | end |
73 | 72 | ||
73 | g = m.P(g) | ||
74 | |||
74 | local function eval(input) | 75 | local function eval(input) |
75 | errors = {} | 76 | errors = {} |
76 | io.write("Input: ", input, "\n") | 77 | io.write("Input: ", input, "\n") |
77 | subject = input | 78 | subject = input |
78 | local result, label, suffix = grec:match(input) | 79 | local result, label, suffix = g:match(input) |
79 | io.write("Syntactic errors found: " .. #errors, "\n") | 80 | io.write("Syntactic errors found: " .. #errors, "\n") |
80 | if #errors > 0 then | 81 | if #errors > 0 then |
81 | local out = {} | 82 | local out = {} |
diff --git a/examples/farthest.lua b/examples/farthest.lua index 9cbe03d..0dc8262 100644 --- a/examples/farthest.lua +++ b/examples/farthest.lua | |||
@@ -15,13 +15,13 @@ function matchPrint2(p, s) | |||
15 | end | 15 | end |
16 | 16 | ||
17 | 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" |
18 | matchPrint(p, "abc") --> r: 3 lab: nil errpos: nil | 18 | matchPrint(p, "abc") --> r: 3 lab: nil errpos: nil |
19 | matchPrint(p, "c") --> r: 2 lab: nil errpos: nil | 19 | matchPrint(p, "c") --> r: 2 lab: nil errpos: nil |
20 | matchPrint(p, "aac") --> r: nil lab: 0 errpos: 3 | 20 | matchPrint(p, "aac") --> r: nil lab: fail errpos: 3 |
21 | matchPrint(p, "xxc") --> r: nil lab: 0 errpos: 1 | 21 | matchPrint(p, "xxc") --> r: nil lab: fail errpos: 1 |
22 | 22 | ||
23 | 23 | ||
24 | matchPrint2(p, "abc") --> r: 3 lab: nil sfail: nil | 24 | matchPrint2(p, "abc") --> r: 3 lab: nil sfail: nil |
25 | matchPrint2(p, "c") --> r: 2 lab: nil sfail: nil | 25 | matchPrint2(p, "c") --> r: 2 lab: nil sfail: nil |
26 | matchPrint2(p, "aac") --> r: nil lab: 0 sfail: c | 26 | matchPrint2(p, "aac") --> r: nil lab: fail sfail: c |
27 | matchPrint2(p, "xxc") --> r: nil lab: 0 sfail: xxc | 27 | matchPrint2(p, "xxc") --> r: nil lab: fail sfail: xxc |
diff --git a/examples/listId1.lua b/examples/listId1.lua index 9bba783..e045ac1 100644 --- a/examples/listId1.lua +++ b/examples/listId1.lua | |||
@@ -7,8 +7,8 @@ local g = m.P{ | |||
7 | "S", | 7 | "S", |
8 | S = m.V"Id" * m.V"List", | 8 | S = m.V"Id" * m.V"List", |
9 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", | 9 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", |
10 | Id = m.V"Sp" * id + m.T(1), | 10 | Id = m.V"Sp" * id + m.T'ErrId', |
11 | Comma = m.V"Sp" * "," + m.T(2), | 11 | Comma = m.V"Sp" * "," + m.T'ErrComma', |
12 | Sp = m.S" \n\t"^0, | 12 | Sp = m.S" \n\t"^0, |
13 | } | 13 | } |
14 | 14 | ||
@@ -17,9 +17,9 @@ function mymatch (g, s) | |||
17 | if not r then | 17 | if not r then |
18 | local line, col = re.calcline(s, pos) | 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 == 'ErrId' then |
21 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" | 21 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" |
22 | elseif e == 2 then | 22 | elseif e == 'ErrComma' then |
23 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" | 23 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" |
24 | else | 24 | else |
25 | return r, msg | 25 | return r, msg |
diff --git a/examples/listId2.lua b/examples/listId2.lua index 592dae3..322d432 100644 --- a/examples/listId2.lua +++ b/examples/listId2.lua | |||
@@ -1,16 +1,11 @@ | |||
1 | local m = require'lpeglabel' | 1 | local m = require'lpeglabel' |
2 | local re = require'relabel' | 2 | local re = require'relabel' |
3 | 3 | ||
4 | local terror = {} | 4 | local terror = { |
5 | 5 | ErrId = "expecting an identifier", | |
6 | local function newError(s) | 6 | ErrComma = "expecting ','", |
7 | table.insert(terror, s) | 7 | fail = "undefined" |
8 | return #terror | 8 | } |
9 | end | ||
10 | |||
11 | local errUndef = newError("undefined") | ||
12 | local errId = newError("expecting an identifier") | ||
13 | local errComma = newError("expecting ','") | ||
14 | 9 | ||
15 | local id = m.R'az'^1 | 10 | local id = m.R'az'^1 |
16 | 11 | ||
@@ -18,8 +13,8 @@ local g = m.P{ | |||
18 | "S", | 13 | "S", |
19 | S = m.V"Id" * m.V"List", | 14 | S = m.V"Id" * m.V"List", |
20 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", | 15 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", |
21 | Id = m.V"Sp" * id + m.T(errId), | 16 | Id = m.V"Sp" * id + m.T'ErrId', |
22 | Comma = m.V"Sp" * "," + m.T(errComma), | 17 | Comma = m.V"Sp" * "," + m.T'ErrComma', |
23 | Sp = m.S" \n\t"^0, | 18 | Sp = m.S" \n\t"^0, |
24 | } | 19 | } |
25 | 20 | ||
diff --git a/examples/listId2Rec2.lua b/examples/listId2Rec2.lua index 3506095..09db5a6 100644 --- a/examples/listId2Rec2.lua +++ b/examples/listId2Rec2.lua | |||
@@ -1,51 +1,39 @@ | |||
1 | local m = require'lpeglabel' | 1 | local m = require'lpeglabel' |
2 | local re = require'relabel' | 2 | local re = require'relabel' |
3 | 3 | ||
4 | local terror = {} | 4 | local terror = { |
5 | 5 | ErrId = "expecting an identifier", | |
6 | local function newError(s) | 6 | ErrComma = "expecting ','" |
7 | table.insert(terror, s) | ||
8 | return #terror | ||
9 | end | ||
10 | |||
11 | local errUndef = newError("undefined") | ||
12 | local errId = newError("expecting an identifier") | ||
13 | local errComma = newError("expecting ','") | ||
14 | |||
15 | local id = m.R'az'^1 | ||
16 | |||
17 | local g = m.P{ | ||
18 | "S", | ||
19 | S = m.V"Id" * m.V"List", | ||
20 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", | ||
21 | Id = m.V"Sp" * id + m.T(errId), | ||
22 | Comma = m.V"Sp" * "," + m.T(errComma), | ||
23 | Sp = m.S" \n\t"^0, | ||
24 | } | 7 | } |
25 | 8 | ||
26 | local subject, errors | 9 | local subject, errors |
27 | 10 | ||
28 | function recorderror(pos, lab) | 11 | local function recorderror(pos, lab) |
29 | local line, col = re.calcline(subject, pos) | 12 | local line, col = re.calcline(subject, pos) |
30 | table.insert(errors, { line = line, col = col, msg = terror[lab] }) | 13 | table.insert(errors, { line = line, col = col, msg = terror[lab] }) |
31 | end | 14 | end |
32 | 15 | ||
33 | function record (lab) | 16 | local function record (lab) |
34 | return (m.Cp() * m.Cc(lab)) / recorderror | 17 | return (m.Cp() * m.Cc(lab)) / recorderror |
35 | end | 18 | end |
36 | 19 | ||
37 | function sync (p) | 20 | local function sync (p) |
38 | return (-p * m.P(1))^0 | 21 | return (-p * m.P(1))^0 |
39 | end | 22 | end |
40 | 23 | ||
41 | local grec = m.P{ | 24 | local id = m.R'az'^1 |
25 | |||
26 | local g = m.P{ | ||
42 | "S", | 27 | "S", |
43 | S = m.Rec(m.Rec(g, m.V"ErrComma", errComma), m.V"ErrId", errId), | 28 | S = m.V"Id" * m.V"List", |
44 | ErrComma = record(errComma) * sync(id), | 29 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", |
45 | ErrId = record(errId) * sync(m.P",") | 30 | Id = m.V"Sp" * id + m.T'ErrId', |
31 | Comma = m.V"Sp" * "," + m.T'ErrComma', | ||
32 | Sp = m.S" \n\t"^0, | ||
33 | ErrId = record('ErrId') * sync(m.P","), | ||
34 | ErrComma = record('ErrComma') * sync(id), | ||
46 | } | 35 | } |
47 | 36 | ||
48 | |||
49 | function mymatch (g, s) | 37 | function mymatch (g, s) |
50 | errors = {} | 38 | errors = {} |
51 | subject = s | 39 | subject = s |
@@ -61,7 +49,7 @@ function mymatch (g, s) | |||
61 | return r | 49 | return r |
62 | end | 50 | end |
63 | 51 | ||
64 | print(mymatch(grec, "one,two")) | 52 | print(mymatch(g, "one,two")) |
65 | print(mymatch(grec, "one two three")) | 53 | print(mymatch(g, "one two three")) |
66 | print(mymatch(grec, "1,\n two, \n3,")) | 54 | print(mymatch(g, "1,\n two, \n3,")) |
67 | print(mymatch(grec, "one\n two123, \nthree,")) | 55 | print(mymatch(g, "one\n two123, \nthree,")) |
diff --git a/examples/listId2Rec2Cap.lua b/examples/listId2Rec2Cap.lua index 32a4113..7fbe700 100644 --- a/examples/listId2Rec2Cap.lua +++ b/examples/listId2Rec2Cap.lua | |||
@@ -1,26 +1,9 @@ | |||
1 | local m = require'lpeglabel' | 1 | local m = require'lpeglabel' |
2 | local re = require'relabel' | 2 | local re = require'relabel' |
3 | 3 | ||
4 | local terror = {} | 4 | local terror = { |
5 | 5 | ErrId = "expecting an identifier", | |
6 | local function newError(s) | 6 | ErrComma = "expecting ','" |
7 | table.insert(terror, s) | ||
8 | return #terror | ||
9 | end | ||
10 | |||
11 | local errUndef = newError("undefined") | ||
12 | local errId = newError("expecting an identifier") | ||
13 | local errComma = newError("expecting ','") | ||
14 | |||
15 | local id = m.R'az'^1 | ||
16 | |||
17 | local g = m.P{ | ||
18 | "S", | ||
19 | S = m.V"Id" * m.V"List", | ||
20 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", | ||
21 | Id = m.V"Sp" * m.C(id) + m.T(errId), | ||
22 | Comma = m.V"Sp" * "," + m.T(errComma), | ||
23 | Sp = m.S" \n\t"^0, | ||
24 | } | 7 | } |
25 | 8 | ||
26 | local subject, errors | 9 | local subject, errors |
@@ -42,11 +25,17 @@ function defaultValue () | |||
42 | return m.Cc"NONE" | 25 | return m.Cc"NONE" |
43 | end | 26 | end |
44 | 27 | ||
45 | local grec = m.P{ | 28 | local id = m.R'az'^1 |
29 | |||
30 | local g = m.P{ | ||
46 | "S", | 31 | "S", |
47 | S = m.Rec(m.Rec(g, m.V"ErrComma", errComma), m.V"ErrId", errId), | 32 | S = m.V"Id" * m.V"List", |
48 | ErrComma = record(errComma) * sync(id), | 33 | List = -m.P(1) + m.V"Comma" * m.V"Id" * m.V"List", |
49 | ErrId = record(errId) * sync(m.P",") * defaultValue(), | 34 | Id = m.V"Sp" * m.C(id) + m.T'ErrId', |
35 | Comma = m.V"Sp" * "," + m.T'ErrComma', | ||
36 | Sp = m.S" \n\t"^0, | ||
37 | ErrId = record('ErrId') * sync(m.P",") * defaultValue(), | ||
38 | ErrComma = record('ErrComma') * sync(id), | ||
50 | } | 39 | } |
51 | 40 | ||
52 | 41 | ||
@@ -73,7 +62,7 @@ function mymatch (g, s) | |||
73 | return r | 62 | return r |
74 | end | 63 | end |
75 | 64 | ||
76 | mymatch(grec, "one,two") | 65 | mymatch(g, "one,two") |
77 | mymatch(grec, "one two three") | 66 | mymatch(g, "one two three") |
78 | mymatch(grec, "1,\n two, \n3,") | 67 | mymatch(g, "1,\n two, \n3,") |
79 | mymatch(grec, "one\n two123, \nthree,") | 68 | mymatch(g, "one\n two123, \nthree,") |
diff --git a/examples/listIdRe1.lua b/examples/listIdRe1.lua index d60706a..ef38cfb 100644 --- a/examples/listIdRe1.lua +++ b/examples/listIdRe1.lua | |||
@@ -3,8 +3,8 @@ local re = require 'relabel' | |||
3 | local g = re.compile[[ | 3 | local g = re.compile[[ |
4 | S <- Id List | 4 | S <- Id List |
5 | List <- !. / Comma Id List | 5 | List <- !. / Comma Id List |
6 | Id <- Sp [a-z]+ / %{2} | 6 | Id <- Sp [a-z]+ / %{ErrId} |
7 | Comma <- Sp ',' / %{3} | 7 | Comma <- Sp ',' / %{ErrComma} |
8 | Sp <- %s* | 8 | Sp <- %s* |
9 | ]] | 9 | ]] |
10 | 10 | ||
@@ -13,9 +13,9 @@ function mymatch (g, s) | |||
13 | if not r then | 13 | if not r then |
14 | local line, col = re.calcline(s, pos) | 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 == 'ErrId' then |
17 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" | 17 | return r, msg .. ": expecting an identifier before '" .. s:sub(pos) .. "'" |
18 | elseif e == 2 then | 18 | elseif e == 'ErrComma' then |
19 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" | 19 | return r, msg .. ": expecting ',' before '" .. s:sub(pos) .. "'" |
20 | else | 20 | else |
21 | return r, msg | 21 | return r, msg |
diff --git a/examples/listIdRe2.lua b/examples/listIdRe2.lua index 58ddedd..0ea7352 100644 --- a/examples/listIdRe2.lua +++ b/examples/listIdRe2.lua | |||
@@ -1,46 +1,33 @@ | |||
1 | local re = require 'relabel' | 1 | local re = require 'relabel' |
2 | 2 | ||
3 | local errinfo = { | 3 | local errinfo = { |
4 | {"errUndef", "undefined"}, | 4 | ErrId = "expecting an identifier", |
5 | {"errId", "expecting an identifier"}, | 5 | ErrComma = "expecting ','", |
6 | {"errComma", "expecting ','"}, | 6 | fail = "undefined", |
7 | } | 7 | } |
8 | 8 | ||
9 | local errmsgs = {} | 9 | local function sync (p) |
10 | local labels = {} | 10 | return '( !(' .. p .. ') .)*' |
11 | |||
12 | for i, err in ipairs(errinfo) do | ||
13 | errmsgs[i] = err[2] | ||
14 | labels[err[1]] = i | ||
15 | end | 11 | end |
16 | 12 | ||
17 | re.setlabels(labels) | ||
18 | |||
19 | local g = re.compile[[ | ||
20 | S <- Id List | ||
21 | List <- !. / Comma Id List | ||
22 | Id <- Sp {[a-z]+} / %{errId} | ||
23 | Comma <- Sp ',' / %{errComma} | ||
24 | Sp <- %s* | ||
25 | ]] | ||
26 | |||
27 | local errors | 13 | local errors |
28 | 14 | ||
29 | function recorderror (subject, pos, label) | 15 | local function recorderror (subject, pos, label) |
30 | local line, col = re.calcline(subject, pos) | 16 | local line, col = re.calcline(subject, pos) |
31 | table.insert(errors, { line = line, col = col, msg = errmsgs[labels[label]] }) | 17 | table.insert(errors, { line = line, col = col, msg = errinfo[label] }) |
32 | return true | 18 | return true |
33 | end | 19 | end |
34 | 20 | ||
35 | function sync (p) | 21 | local g = re.compile([[ |
36 | return '( !(' .. p .. ') .)*' | 22 | S <- Id List |
37 | end | 23 | List <- !. / Comma Id List |
24 | Id <- (Sp {[a-z]+})^ErrId | ||
25 | Comma <- (Sp ',')^ErrComma | ||
26 | Sp <- %s*]] .. | ||
27 | "ErrId <- ('' -> 'ErrId' => recorderror) " .. sync('","') .. "-> default\n" .. | ||
28 | "ErrComma <- ('' -> 'ErrComma' => recorderror) " .. sync('[a-z]+'), | ||
29 | {default = "NONE", recorderror = recorderror}) | ||
38 | 30 | ||
39 | local grec = re.compile( | ||
40 | "S <- %g //{errComma} ErrComma //{errId} ErrId" .. "\n" .. | ||
41 | "ErrComma <- ('' -> 'errComma' => recorderror) " .. sync('[a-z]+') .. "\n" .. | ||
42 | "ErrId <- ('' -> 'errId' => recorderror) " .. sync('","') .. "-> default" | ||
43 | , {g = g, recorderror = recorderror, default = "NONE"}) | ||
44 | 31 | ||
45 | function mymatch (g, s) | 32 | function mymatch (g, s) |
46 | errors = {} | 33 | errors = {} |
@@ -65,7 +52,7 @@ function mymatch (g, s) | |||
65 | return r | 52 | return r |
66 | end | 53 | end |
67 | 54 | ||
68 | mymatch(grec, "one,two") | 55 | mymatch(g, "one,two") |
69 | mymatch(grec, "one two three") | 56 | mymatch(g, "one two three") |
70 | mymatch(grec, "1,\n two, \n3,") | 57 | mymatch(g, "1,\n two, \n3,") |
71 | mymatch(grec, "one\n two123, \nthree,") | 58 | mymatch(g, "one\n two123, \nthree,") |
diff --git a/examples/tiny.lua b/examples/tiny.lua index cc718e7..fe0bced 100644 --- a/examples/tiny.lua +++ b/examples/tiny.lua | |||
@@ -1,92 +1,63 @@ | |||
1 | local re = require 'relabel' | 1 | local re = require 'relabel' |
2 | 2 | ||
3 | local terror = {} | 3 | local terror = { |
4 | 4 | cmdSeq = "Missing ';' in CmdSeq", | |
5 | local function newError(l, msg) | 5 | ifExp = "Error in expresion of 'if'", |
6 | table.insert(terror, { l = l, msg = msg} ) | 6 | ifThen = "Error matching 'then' keyword", |
7 | end | 7 | ifThenCmdSeq = "Error matching CmdSeq of 'then' branch", |
8 | 8 | ifElseCmdSeq = "Error matching CmdSeq of 'else' branch", | |
9 | newError("errSemi", "Error: missing ';'") | 9 | ifEnd = "Error matching 'end' keyword of 'if'", |
10 | newError("errExpIf", "Error: expected expression after 'if'") | 10 | repeatCmdSeq = "Error matching CmdSeq of 'repeat'", |
11 | newError("errThen", "Error: expected 'then' keyword") | 11 | repeatUntil = "Error matching 'until' keyword", |
12 | newError("errCmdSeq1", "Error: expected at least a command after 'then'") | 12 | repeatExp = "Error matching expression of 'until'", |
13 | newError("errCmdSeq2", "Error: expected at least a command after 'else'") | 13 | assignOp = "Error matching ':='", |
14 | newError("errEnd", "Error: expected 'end' keyword") | 14 | assignExp = "Error matching expression of assignment", |
15 | newError("errCmdSeqRep", "Error: expected at least a command after 'repeat'") | 15 | readName = "Error matching 'NAME' after 'read'", |
16 | newError("errUntil", "Error: expected 'until' keyword") | 16 | writeExp = "Error matching expression after 'write'", |
17 | newError("errExpRep", "Error: expected expression after 'until'") | 17 | simpleExp = "Error matching 'SimpleExp'", |
18 | newError("errAssignOp", "Error: expected ':=' in assigment") | 18 | term = "Error matching 'Term'", |
19 | newError("errExpAssign", "Error: expected expression after ':='") | 19 | factor = "Error matching 'Factor'", |
20 | newError("errReadName", "Error: expected an identifier after 'read'") | 20 | openParExp = "Error matching expression after '('", |
21 | newError("errWriteExp", "Error: expected expression after 'write'") | 21 | closePar = "Error matching ')'", |
22 | newError("errSimpExp", "Error: expected '(', ID, or number after '<' or '='") | 22 | undefined = "Undefined Error" |
23 | newError("errTerm", "Error: expected '(', ID, or number after '+' or '-'") | 23 | } |
24 | newError("errFactor", "Error: expected '(', ID, or number after '*' or '/'") | 24 | |
25 | newError("errExpFac", "Error: expected expression after '('") | 25 | g = re.compile([[ |
26 | newError("errClosePar", "Error: expected ')' after expression") | 26 | Tiny <- CmdSeq^undefined |
27 | 27 | CmdSeq <- (Cmd SEMICOLON^cmdSeq) (Cmd SEMICOLON^cmdSeq)* | |
28 | 28 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd | |
29 | local labelCode = {} | 29 | IfCmd <- IF Exp^ifExp THEN^ifThen CmdSeq^ifThenCmdSeq (ELSE CmdSeq^ifElseCmdSeq / '') END^ifEnd |
30 | for k, v in ipairs(terror) do | 30 | RepeatCmd <- REPEAT CmdSeq^repeatCmdSeq UNTIL^repeatUntil Exp^repeatExp |
31 | labelCode[v.l] = k | 31 | AssignCmd <- NAME ASSIGNMENT^assignOp Exp^assignExp |
32 | end | 32 | ReadCmd <- READ NAME^readName |
33 | 33 | WriteCmd <- WRITE Exp^writeExp | |
34 | re.setlabels(labelCode) | 34 | Exp <- SimpleExp ((LESS / EQUAL) SimpleExp^simpleExp / '') |
35 | 35 | SimpleExp <- Term ((ADD / SUB) Term^term)* | |
36 | local g = re.compile[[ | 36 | Term <- Factor ((MUL / DIV) Factor^factor)* |
37 | Tiny <- CmdSeq | 37 | Factor <- OPENPAR Exp^openParExp CLOSEPAR^closePar / NUMBER / NAME |
38 | CmdSeq <- (Cmd (SEMICOLON / ErrSemi)) (Cmd (SEMICOLON / ErrSemi))* | 38 | ADD <- Sp '+' |
39 | Cmd <- IfCmd / RepeatCmd / ReadCmd / WriteCmd / AssignCmd | 39 | ASSIGNMENT <- Sp ':=' |
40 | IfCmd <- IF (Exp / ErrExpIf) (THEN / ErrThen) (CmdSeq / ErrCmdSeq1) (ELSE (CmdSeq / ErrCmdSeq2) / '') (END / ErrEnd) | 40 | CLOSEPAR <- Sp ')' |
41 | RepeatCmd <- REPEAT (CmdSeq / ErrCmdSeqRep) (UNTIL / ErrUntil) (Exp / ErrExpRep) | 41 | DIV <- Sp '/' |
42 | AssignCmd <- NAME (ASSIGNMENT / ErrAssignOp) (Exp / ErrExpAssign) | 42 | IF <- Sp 'if' |
43 | ReadCmd <- READ (NAME / ErrReadName) | 43 | ELSE <- Sp 'else' |
44 | WriteCmd <- WRITE (Exp / ErrWriteExp) | 44 | END <- Sp 'end' |
45 | Exp <- SimpleExp ((LESS / EQUAL) (SimpleExp / ErrSimpExp) / '') | 45 | EQUAL <- Sp '=' |
46 | SimpleExp <- Term ((ADD / SUB) (Term / ErrTerm))* | 46 | LESS <- Sp '<' |
47 | Term <- Factor ((MUL / DIV) (Factor / ErrFactor))* | 47 | MUL <- Sp '*' |
48 | Factor <- OPENPAR (Exp / ErrExpFac) (CLOSEPAR / ErrClosePar) / NUMBER / NAME | 48 | NAME <- !RESERVED Sp [a-z]+ |
49 | ErrSemi <- %{errSemi} | 49 | NUMBER <- Sp [0-9]+ |
50 | ErrExpIf <- %{errExpIf} | 50 | OPENPAR <- Sp '(' |
51 | ErrThen <- %{errThen} | 51 | READ <- Sp 'read' |
52 | ErrCmdSeq1 <- %{errCmdSeq1} | 52 | REPEAT <- Sp 'repeat' |
53 | ErrCmdSeq2 <- %{errCmdSeq2} | 53 | SEMICOLON <- Sp ';' |
54 | ErrEnd <- %{errEnd} | 54 | SUB <- Sp '-' |
55 | ErrCmdSeqRep <- %{errCmdSeqRep} | 55 | THEN <- Sp 'then' |
56 | ErrUntil <- %{errUntil} | 56 | UNTIL <- Sp 'until' |
57 | ErrExpRep <- %{errExpRep} | 57 | WRITE <- Sp 'write' |
58 | ErrAssignOp <- %{errAssignOp} | 58 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ |
59 | ErrExpAssign <- %{errExpAssign} | 59 | Sp <- (%s / %nl)* |
60 | ErrReadName <- %{errReadName} | 60 | ]], terror) |
61 | ErrWriteExp <- %{errWriteExp} | ||
62 | ErrSimpExp <- %{errSimpExp} | ||
63 | ErrTerm <- %{errTerm} | ||
64 | ErrFactor <- %{errFactor} | ||
65 | ErrExpFac <- %{errExpFac} | ||
66 | ErrClosePar <- %{errClosePar} | ||
67 | ADD <- Sp '+' | ||
68 | ASSIGNMENT <- Sp ':=' | ||
69 | CLOSEPAR <- Sp ')' | ||
70 | DIV <- Sp '/' | ||
71 | IF <- Sp 'if' | ||
72 | ELSE <- Sp 'else' | ||
73 | END <- Sp 'end' | ||
74 | EQUAL <- Sp '=' | ||
75 | LESS <- Sp '<' | ||
76 | MUL <- Sp '*' | ||
77 | NAME <- Sp !RESERVED [a-z]+ | ||
78 | NUMBER <- Sp [0-9]+ | ||
79 | OPENPAR <- Sp '(' | ||
80 | READ <- Sp 'read' | ||
81 | REPEAT <- Sp 'repeat' | ||
82 | SEMICOLON <- Sp ';' | ||
83 | SUB <- Sp '-' | ||
84 | THEN <- Sp 'then' | ||
85 | UNTIL <- Sp 'until' | ||
86 | WRITE <- Sp 'write' | ||
87 | RESERVED <- (IF / ELSE / END / READ / REPEAT / THEN / UNTIL / WRITE) ![a-z]+ | ||
88 | Sp <- %s* | ||
89 | ]] | ||
90 | 61 | ||
91 | 62 | ||
92 | local function mymatch(g, s) | 63 | local function mymatch(g, s) |
@@ -94,7 +65,7 @@ local function mymatch(g, s) | |||
94 | if not r then | 65 | if not r then |
95 | local line, col = re.calcline(s, pos) | 66 | local line, col = re.calcline(s, pos) |
96 | local msg = "Error at line " .. line .. " (col " .. col .. "): " | 67 | local msg = "Error at line " .. line .. " (col " .. col .. "): " |
97 | return r, msg .. terror[e].msg | 68 | return r, msg .. terror[e] |
98 | end | 69 | end |
99 | return r | 70 | return r |
100 | end | 71 | end |
@@ -351,10 +351,6 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e, | |||
351 | while (!(stack-1)->predchoice) { | 351 | while (!(stack-1)->predchoice) { |
352 | --stack; | 352 | --stack; |
353 | } | 353 | } |
354 | /*if ((stack-1)->labenv == ANDPRED) { | ||
355 | printf("ANDPRED: stack - 1\n"); | ||
356 | stack--; | ||
357 | }*/ | ||
358 | *labelf = LFAIL; | 354 | *labelf = LFAIL; |
359 | } | 355 | } |
360 | goto fail; | 356 | goto fail; |