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