aboutsummaryrefslogtreecommitdiff
path: root/examples/expRecAut.lua
diff options
context:
space:
mode:
Diffstat (limited to 'examples/expRecAut.lua')
-rw-r--r--examples/expRecAut.lua122
1 files changed, 122 insertions, 0 deletions
diff --git a/examples/expRecAut.lua b/examples/expRecAut.lua
new file mode 100644
index 0000000..f870d73
--- /dev/null
+++ b/examples/expRecAut.lua
@@ -0,0 +1,122 @@
1local m = require"lpeglabelrec"
2local re = require"relabelrec"
3
4local num = m.R("09")^1 / tonumber
5local op = m.S("+-")
6
7local labels = {}
8local nlabels = 0
9
10local function newError(lab, msg, psync, pcap)
11 nlabels = nlabels + 1
12 psync = psync or m.P(-1)
13 pcap = pcap or m.P""
14 labels[lab] = { id = nlabels, msg = msg, psync = psync, pcap = pcap }
15end
16
17newError("ExpTermFirst", "expected an expression", op + ")", m.Cc(1000))
18newError("ExpTermOp", "expected a term after the operator", op + ")", m.Cc(1000))
19newError("MisClose", "missing a closing ')' after the expression", m.P")")
20newError("Extra", "extra characters found after the expression")
21
22local errors, subject
23
24local function expect(patt, labname)
25 local i = labels[labname].id
26 return patt + m.T(i)
27end
28
29local 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 else
37 error('unknown operation: ' .. tokens[i])
38 end
39 end
40 return result
41end
42
43local 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
52function recorderror(pos, lab)
53 local line, col = re.calcline(subject, pos)
54 table.insert(errors, { line = line, col = col, msg = labels[lab].msg })
55end
56
57function record (labname)
58 return (m.Cp() * m.Cc(labname)) / recorderror
59end
60
61function sync (p)
62 return (-p * m.P(1))^0
63end
64
65function defaultValue (p)
66 return p or m.Cc(1000)
67end
68
69local grec = g * expect(m.P(-1), "Extra")
70for k, v in pairs(labels) do
71 grec = m.Rec(grec, record(k) * sync(v.psync) * v.pcap, v.id)
72end
73
74local function eval(input)
75 errors = {}
76 io.write("Input: ", input, "\n")
77 subject = input
78 local result, label, suffix = grec:match(input)
79 io.write("Syntactic errors found: " .. #errors, "\n")
80 if #errors > 0 then
81 local out = {}
82 for i, err in ipairs(errors) do
83 local pos = err.col
84 local msg = err.msg
85 table.insert(out, "syntax error: " .. msg .. " (at index " .. pos .. ")")
86 end
87 print(table.concat(out, "\n"))
88 end
89 io.write("Result = ")
90 return result
91end
92
93print(eval "90-70-(5)+3")
94--> 18
95
96print(eval "15+")
97--> 2 + 0
98
99print(eval "-2")
100--> 0 - 2
101
102print(eval "1+3+-9")
103--> 1 + 3 + [0] - 9
104
105print(eval "1+()3+")
106--> 1 + ([0]) [+] 3 + [0]
107
108print(eval "8-(2+)-5")
109--> 8 - (2 + [0]) - 5
110
111print(eval "()")
112
113print(eval "")
114
115print(eval "1+()+")
116
117print(eval "1+(")
118
119print(eval "3)")
120
121print(eval "11+()3")
122--> 1 + ([0]) [+] 3 + [0]