From e16a4b989cc2275f7c8601bb44b6c21ff22e12e5 Mon Sep 17 00:00:00 2001 From: Undecidable Robot Date: Thu, 16 Jun 2016 00:51:22 +0800 Subject: Adding a simple example using 'expect' --- examples/expect.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/expect.md (limited to 'examples') diff --git a/examples/expect.md b/examples/expect.md new file mode 100644 index 0000000..544a55e --- /dev/null +++ b/examples/expect.md @@ -0,0 +1,66 @@ +Here's an example of an LPegLabel grammar that make its own function called +'expect', which takes a pattern and a label as parameters and throws the label +if the pattern fails to be matched. This function can be extended later on to +record all errors encountered once error recovery is implemented. + +```lua +local lpeg = require"lpeglabel" + +local R, S, P, V, T = lpeg.R, lpeg.S, lpeg.P, lpeg.V, lpeg.T + +local labels = { + {"NoExp", "no expression found"}, + {"Extra", "extra chracters found after the expression"}, + {"ExpTerm", "expected a term after the operator"}, + {"ExpExp", "expected an expression after the parenthesis"}, + {"MisClose", "missing a closing ')' after the expression"}, +} + +local function expect(patt, labname) + for i, elem in ipairs(labels) do + if elem[1] == labname then + return patt + T(i) + end + end + + error("could not find label: " .. labname) +end + +local num = R("09")^1 +local op = S("+-*/") + +local g = P { + "Exp", + Exp = V"Term" * (op * expect(V"Term", "ExpTerm"))^0; + Term = num + V"Group"; + Group = "(" * expect(V"Exp", "ExpExp") * expect(")", "MisClose"); +} + +g = expect(g, "NoExp") * expect(-P(1), "Extra") + +local function check(input) + result, label, suffix = g:match(input) + if result ~= nil then + return "ok" + else + local pos = input:len() - suffix:len() + 1 + local msg = labels[label][2] + return "syntax error: " .. msg .. " (at index " .. pos .. ")" + end +end + +print(check "(1+1-1*2/2") +--> syntax error: missing a closing ')' after the expression (at index 11) + +print(check "(1+)-1*(2/2)") +--> syntax error: expected a term after the operator (at index 4) + +print(check "(1+1)-1*(/2)") +--> syntax error: expected an expression after the parenthesis (at index 10) + +print(check "1+(1-(1*2))/2x") +--> syntax error: extra chracters found after the expression (at index 14) + +print(check "-1+(1-(1*2))/2") +--> syntax error: no expression found (at index 1) +``` -- cgit v1.2.3-55-g6feb From 816675350aae1ae1e4f9e98bced0dd5ddd413d1c Mon Sep 17 00:00:00 2001 From: Undecidable Robot Date: Thu, 16 Jun 2016 09:52:47 +0800 Subject: Adding evaluation to the example --- examples/expect.md | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'examples') diff --git a/examples/expect.md b/examples/expect.md index 544a55e..469f1d4 100644 --- a/examples/expect.md +++ b/examples/expect.md @@ -6,7 +6,7 @@ record all errors encountered once error recovery is implemented. ```lua local lpeg = require"lpeglabel" -local R, S, P, V, T = lpeg.R, lpeg.S, lpeg.P, lpeg.V, lpeg.T +local R, S, P, V, C, Ct, T = lpeg.R, lpeg.S, lpeg.P, lpeg.V, lpeg.C, lpeg.Ct, lpeg.T local labels = { {"NoExp", "no expression found"}, @@ -26,41 +26,62 @@ local function expect(patt, labname) error("could not find label: " .. labname) end -local num = R("09")^1 +local num = R("09")^1 / tonumber local op = S("+-*/") +local function compute(tokens) + local result = tokens[1] + for i = 2, #tokens, 2 do + if tokens[i] == '+' then + result = result + tokens[i+1] + elseif tokens[i] == '-' then + result = result - tokens[i+1] + elseif tokens[i] == '*' then + result = result * tokens[i+1] + elseif tokens[i] == '/' then + result = result / tokens[i+1] + else + error('unknown operation: ' .. tokens[i]) + end + end + return result +end + local g = P { "Exp", - Exp = V"Term" * (op * expect(V"Term", "ExpTerm"))^0; + Exp = Ct(V"Term" * (C(op) * expect(V"Term", "ExpTerm"))^0) / compute; Term = num + V"Group"; Group = "(" * expect(V"Exp", "ExpExp") * expect(")", "MisClose"); } g = expect(g, "NoExp") * expect(-P(1), "Extra") -local function check(input) - result, label, suffix = g:match(input) +local function eval(input) + local result, label, suffix = g:match(input) if result ~= nil then - return "ok" + return result else local pos = input:len() - suffix:len() + 1 local msg = labels[label][2] - return "syntax error: " .. msg .. " (at index " .. pos .. ")" + return nil, "syntax error: " .. msg .. " (at index " .. pos .. ")" end end -print(check "(1+1-1*2/2") +print(eval "98-76*(54/32)") +--> 37.125 + +print(eval "(1+1-1*2/2") --> syntax error: missing a closing ')' after the expression (at index 11) -print(check "(1+)-1*(2/2)") +print(eval "(1+)-1*(2/2)") --> syntax error: expected a term after the operator (at index 4) -print(check "(1+1)-1*(/2)") +print(eval "(1+1)-1*(/2)") --> syntax error: expected an expression after the parenthesis (at index 10) -print(check "1+(1-(1*2))/2x") +print(eval "1+(1-(1*2))/2x") --> syntax error: extra chracters found after the expression (at index 14) -print(check "-1+(1-(1*2))/2") +print(eval "-1+(1-(1*2))/2") --> syntax error: no expression found (at index 1) ``` -- cgit v1.2.3-55-g6feb From c74eb058fe98d1d482954ad91a5e1b5805e225ff Mon Sep 17 00:00:00 2001 From: Undecidable Robot Date: Fri, 24 Jun 2016 01:15:10 +0800 Subject: Fixing a typo in the example --- examples/expect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/expect.md b/examples/expect.md index 469f1d4..d7d2d3e 100644 --- a/examples/expect.md +++ b/examples/expect.md @@ -10,7 +10,7 @@ local R, S, P, V, C, Ct, T = lpeg.R, lpeg.S, lpeg.P, lpeg.V, lpeg.C, lpeg.Ct, lp local labels = { {"NoExp", "no expression found"}, - {"Extra", "extra chracters found after the expression"}, + {"Extra", "extra characters found after the expression"}, {"ExpTerm", "expected a term after the operator"}, {"ExpExp", "expected an expression after the parenthesis"}, {"MisClose", "missing a closing ')' after the expression"}, -- cgit v1.2.3-55-g6feb