aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/expect.md87
1 files changed, 87 insertions, 0 deletions
diff --git a/examples/expect.md b/examples/expect.md
new file mode 100644
index 0000000..d7d2d3e
--- /dev/null
+++ b/examples/expect.md
@@ -0,0 +1,87 @@
1Here's an example of an LPegLabel grammar that make its own function called
2'expect', which takes a pattern and a label as parameters and throws the label
3if the pattern fails to be matched. This function can be extended later on to
4record all errors encountered once error recovery is implemented.
5
6```lua
7local lpeg = require"lpeglabel"
8
9local R, S, P, V, C, Ct, T = lpeg.R, lpeg.S, lpeg.P, lpeg.V, lpeg.C, lpeg.Ct, lpeg.T
10
11local labels = {
12 {"NoExp", "no expression found"},
13 {"Extra", "extra characters found after the expression"},
14 {"ExpTerm", "expected a term after the operator"},
15 {"ExpExp", "expected an expression after the parenthesis"},
16 {"MisClose", "missing a closing ')' after the expression"},
17}
18
19local function expect(patt, labname)
20 for i, elem in ipairs(labels) do
21 if elem[1] == labname then
22 return patt + T(i)
23 end
24 end
25
26 error("could not find label: " .. labname)
27end
28
29local num = R("09")^1 / tonumber
30local op = S("+-*/")
31
32local function compute(tokens)
33 local result = tokens[1]
34 for i = 2, #tokens, 2 do
35 if tokens[i] == '+' then
36 result = result + tokens[i+1]
37 elseif tokens[i] == '-' then
38 result = result - tokens[i+1]
39 elseif tokens[i] == '*' then
40 result = result * tokens[i+1]
41 elseif tokens[i] == '/' then
42 result = result / tokens[i+1]
43 else
44 error('unknown operation: ' .. tokens[i])
45 end
46 end
47 return result
48end
49
50local g = P {
51 "Exp",
52 Exp = Ct(V"Term" * (C(op) * expect(V"Term", "ExpTerm"))^0) / compute;
53 Term = num + V"Group";
54 Group = "(" * expect(V"Exp", "ExpExp") * expect(")", "MisClose");
55}
56
57g = expect(g, "NoExp") * expect(-P(1), "Extra")
58
59local function eval(input)
60 local result, label, suffix = g:match(input)
61 if result ~= nil then
62 return result
63 else
64 local pos = input:len() - suffix:len() + 1
65 local msg = labels[label][2]
66 return nil, "syntax error: " .. msg .. " (at index " .. pos .. ")"
67 end
68end
69
70print(eval "98-76*(54/32)")
71--> 37.125
72
73print(eval "(1+1-1*2/2")
74--> syntax error: missing a closing ')' after the expression (at index 11)
75
76print(eval "(1+)-1*(2/2)")
77--> syntax error: expected a term after the operator (at index 4)
78
79print(eval "(1+1)-1*(/2)")
80--> syntax error: expected an expression after the parenthesis (at index 10)
81
82print(eval "1+(1-(1*2))/2x")
83--> syntax error: extra chracters found after the expression (at index 14)
84
85print(eval "-1+(1-(1*2))/2")
86--> syntax error: no expression found (at index 1)
87```