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; |
