aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/expectWithRecovRe.lua114
1 files changed, 114 insertions, 0 deletions
diff --git a/examples/expectWithRecovRe.lua b/examples/expectWithRecovRe.lua
new file mode 100644
index 0000000..c424160
--- /dev/null
+++ b/examples/expectWithRecovRe.lua
@@ -0,0 +1,114 @@
1local lpeg = require"lpeglabel"
2local re = require"relabel"
3
4local R, S, P, V = lpeg.R, lpeg.S, lpeg.P, lpeg.V
5local C, Cc, Ct, Cmt = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cmt
6local T, Lc = lpeg.T, lpeg.Lc
7
8local errinfo = {
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
16local labels = {}
17local errmsgs = {}
18
19for i, err in ipairs(errinfo) do
20 labels[err[1]] = i
21 errmsgs[err[1]] = err[2]
22end
23
24re.setlabels(labels)
25
26local errors = {}
27
28function recordError(input, pos, label)
29 table.insert(errors, {label, pos})
30 return true
31end
32
33local function compute(tokens)
34 local result = tokens[1]
35 for i = 2, #tokens, 2 do
36 if tokens[i] == '+' then
37 result = result + tokens[i+1]
38 elseif tokens[i] == '-' then
39 result = result - tokens[i+1]
40 elseif tokens[i] == '*' then
41 result = result * tokens[i+1]
42 elseif tokens[i] == '/' then
43 result = result / tokens[i+1]
44 else
45 error('unknown operation: ' .. tokens[i])
46 end
47 end
48 return result
49end
50
51local g = re.compile([[
52 S <- (Exp / ErrNoExp) (!. / ErrExtra)
53 Exp <- {| Term (op Operand)* |} -> compute
54 Operand <- Term / ErrExpTerm /{ExpTerm} dummy
55 Term <- num / Group
56 Group <- "(" InnerExp (")" / ErrMisClose /{MisClose} "")
57 InnerExp <- Exp / ErrExpExp /{ExpExp} [^)]* dummy
58
59 op <- {[-+*/]}
60 num <- [0-9]+ -> tonumber
61
62 ErrNoExp <- ("" -> "NoExp" => recordError) %{NoExp}
63 ErrExtra <- ("" -> "Extra" => recordError) %{Extra}
64 ErrExpTerm <- ("" -> "ExpTerm" => recordError) %{ExpTerm}
65 ErrExpExp <- ("" -> "ExpExp" => recordError) %{ExpExp}
66 ErrMisClose <- ("" -> "MisClose" => recordError) %{MisClose}
67
68 dummy <- "" -> "0" -> tonumber
69]], {
70 compute = compute;
71 recordError = recordError;
72 tonumber = tonumber;
73})
74
75local function eval(input)
76 local result, label, suffix = g:match(input)
77 if #errors == 0 then
78 return result
79 else
80 local out = ""
81 for i, err in ipairs(errors) do
82 local pos = err[2]
83 local msg = errmsgs[err[1]]
84 local line, col = re.calcline(input, pos)
85 out = out .. "syntax error: " .. msg .. " (line " .. line .. ", col " .. col .. ")\n"
86 end
87 errors = {}
88 return nil, out
89 end
90end
91
92print(eval "98-76*(54/32)")
93--> 37.125
94
95print(eval "(1+1-1*2/2")
96--> syntax error: missing a closing ')' after the expression (line 1, col 10)
97
98print(eval "(1+)-1*(2/2)")
99--> syntax error: expected a term after the operator (line 1, col 4)
100
101print(eval "(1+1)-1*(/2)")
102--> syntax error: expected an expression after the parenthesis (line 1, col 10)
103
104print(eval "1+(1-(1*2))/2x")
105--> syntax error: extra characters found after the expression (line 1, col 14)
106
107print(eval "-1+(1-(1*2))/2")
108--> syntax error: no expression found (line 1, col 1)
109
110print(eval "(1+1-1*(2/2+)-():")
111--> syntax error: expected a term after the operator (line 1, col 13)
112--> syntax error: expected an expression after the parenthesis (line 1, col 16)
113--> syntax error: missing a closing ')' after the expression (line 1, col 17)
114--> syntax error: extra characters found after the expression (line 1, col 17)