diff options
author | David Walter Seikel | 2012-01-23 21:58:02 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-23 21:58:02 +1000 |
commit | 2d1df4714e2736dbde7855ddcd76b4c1de822fa5 (patch) | |
tree | c80e4622631c92dbe8dd6375d187702d084c2f2b /LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools | |
parent | Remove the conflict, and the comment. lol (diff) | |
download | SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.zip SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.gz SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.bz2 SledjHamr-2d1df4714e2736dbde7855ddcd76b4c1de822fa5.tar.xz |
Added a big bunch of example lua scripts for testing the speed of lua compiling.
Diffstat (limited to 'LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools')
3 files changed, 601 insertions, 0 deletions
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua new file mode 100644 index 0000000..5c60e17 --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/call_graph.lua | |||
@@ -0,0 +1,254 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | call_graph.lua | ||
4 | Call graph generator. | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net> | ||
8 | The COPYRIGHT file describes the conditions | ||
9 | under which this software may be distributed. | ||
10 | |||
11 | See the ChangeLog for more information. | ||
12 | |||
13 | ----------------------------------------------------------------------]] | ||
14 | |||
15 | --[[-------------------------------------------------------------------- | ||
16 | -- Notes: | ||
17 | -- * the call tracer wraps function calls in tables to do its work | ||
18 | -- * not very elegant as the namespace of the table/module is affected | ||
19 | -- * tracing using the debugger is probably much more powerful... | ||
20 | -- * use of braces {} allows editors to match braces in the output | ||
21 | -- and do folding, if such facilities are available; for example, the | ||
22 | -- output looks better if Lua syntax highlighting is used on SciTE | ||
23 | ----------------------------------------------------------------------]] | ||
24 | |||
25 | ------------------------------------------------------------------------ | ||
26 | -- options | ||
27 | ------------------------------------------------------------------------ | ||
28 | |||
29 | local SHOW_EXPDESC = true -- show expdesc struct data | ||
30 | |||
31 | ------------------------------------------------------------------------ | ||
32 | -- load and initialize modules | ||
33 | ------------------------------------------------------------------------ | ||
34 | require("../lzio.lua") | ||
35 | require("../llex.lua") | ||
36 | require("../lopcodes.lua") | ||
37 | require("../ldump.lua") | ||
38 | require("../lcode.lua") | ||
39 | require("../lparser.lua") | ||
40 | |||
41 | function lua_assert(test) | ||
42 | if not test then error("assertion failed!") end | ||
43 | end | ||
44 | luaX:init() | ||
45 | local LuaState = {} | ||
46 | |||
47 | ------------------------------------------------------------------------ | ||
48 | -- call graph generator | ||
49 | -- * (1) logging functions, (2) the wrapper initializer itself | ||
50 | ------------------------------------------------------------------------ | ||
51 | |||
52 | llog = {} | ||
53 | |||
54 | ------------------------------------------------------------------------ | ||
55 | -- initialize log file; the usual mode is append; can use stdout/stderr | ||
56 | ------------------------------------------------------------------------ | ||
57 | function llog:init(filename) | ||
58 | if filename == "stdout" then self.h = io.stdout | ||
59 | elseif filename == "stderr" then self.h = io.stderr | ||
60 | else | ||
61 | self.h = io.open(filename, "ab") | ||
62 | if not self.h then | ||
63 | error("can't open log file "..filename.."for writing") | ||
64 | end | ||
65 | end | ||
66 | self.h:write("\n-- start of log --\n\n") | ||
67 | end | ||
68 | |||
69 | ------------------------------------------------------------------------ | ||
70 | -- cleanly closes log file | ||
71 | ------------------------------------------------------------------------ | ||
72 | function llog:exit() | ||
73 | self.h:write("\n-- end of log --\n\n") | ||
74 | if self.h ~= io.stdout and self.h ~= io.stderr then | ||
75 | self.h:close() | ||
76 | end | ||
77 | end | ||
78 | |||
79 | ------------------------------------------------------------------------ | ||
80 | -- logs a message at a particular call depth | ||
81 | ------------------------------------------------------------------------ | ||
82 | function llog:msg(msg, level) | ||
83 | if level then msg = string.rep(" ", level)..msg end | ||
84 | self.h:write(msg) | ||
85 | self.h:flush() | ||
86 | end | ||
87 | |||
88 | ------------------------------------------------------------------------ | ||
89 | -- set up wrapper functions to do tracing on a per-module basis | ||
90 | ------------------------------------------------------------------------ | ||
91 | function llog:calltrace(parms) | ||
92 | ------------------------------------------------------------------ | ||
93 | -- process parameters | ||
94 | ------------------------------------------------------------------ | ||
95 | local module = parms.module | ||
96 | local modulename = parms.modulename | ||
97 | if type(module) ~= "table" then | ||
98 | error("module table parameter required") | ||
99 | elseif not modulename then | ||
100 | error("module name parameter required") | ||
101 | end | ||
102 | ------------------------------------------------------------------ | ||
103 | -- use either allow or deny list | ||
104 | ------------------------------------------------------------------ | ||
105 | local allow = parms.allow or {} | ||
106 | local deny = parms.deny or {} | ||
107 | if table.getn(allow) > 0 and table.getn(deny) > 0 then | ||
108 | error("can't apply both allow and deny lists at the same time") | ||
109 | end | ||
110 | ------------------------------------------------------------------ | ||
111 | -- select functions to wrap | ||
112 | ------------------------------------------------------------------ | ||
113 | local flist = {} | ||
114 | for i, f in pairs(module) do | ||
115 | local wrapthis | ||
116 | if table.getn(allow) > 0 then -- allow some only | ||
117 | wrapthis = false | ||
118 | for j, v in ipairs(allow) do | ||
119 | if i == v then wrapthis = true; break end | ||
120 | end | ||
121 | elseif table.getn(deny) > 0 then -- deny some only | ||
122 | wrapthis = true | ||
123 | for j, v in ipairs(deny) do | ||
124 | if i == v then wrapthis = false; break end | ||
125 | end | ||
126 | else -- default include | ||
127 | wrapthis = true | ||
128 | end | ||
129 | if wrapthis then flist[i] = f end | ||
130 | end | ||
131 | ------------------------------------------------------------------ | ||
132 | -- wrapped function(s) in a module for tracing | ||
133 | ------------------------------------------------------------------ | ||
134 | llog.level = 0 -- nesting level | ||
135 | for i, f in pairs(flist) do | ||
136 | local ModuleName = modulename..":" | ||
137 | local OldName, OldFunc = i, f | ||
138 | if type(OldFunc) == "function" then | ||
139 | local NewName = "__"..OldName | ||
140 | while module[NewName] ~= nil do -- avoid collisions | ||
141 | NewName = "_"..NewName | ||
142 | end | ||
143 | module[NewName] = OldFunc | ||
144 | module[OldName] = | ||
145 | ---------------------------------------------------------- | ||
146 | -- wrapper function for a module's function | ||
147 | -- old function XYZ is renamed __XYZ | ||
148 | ---------------------------------------------------------- | ||
149 | function(self, ...) | ||
150 | local parms = " (" | ||
151 | local exps = {} | ||
152 | -- look for expdesc structs, identify FuncState structs too | ||
153 | local function checkexpdesc(v) | ||
154 | local typ = type(v) | ||
155 | if typ == "table" then | ||
156 | if v.code then return "func" | ||
157 | elseif v.L then return "ls" | ||
158 | elseif v.seminfo then return "token" | ||
159 | elseif v.k then | ||
160 | table.insert(exps, v) | ||
161 | return "exp"..table.getn(exps) | ||
162 | end | ||
163 | end | ||
164 | return typ | ||
165 | end | ||
166 | -- format parameters for printing | ||
167 | for i,v in ipairs(arg) do | ||
168 | if type(v) == "number" then parms = parms..v.."," | ||
169 | elseif type(v) == "string" then parms = parms.."'"..v.."'," | ||
170 | elseif type(v) == "boolean" then parms = parms..tostring(v).."," | ||
171 | elseif SHOW_EXPDESC then parms = parms..checkexpdesc(v).."," | ||
172 | else parms = parms..type(v).."," | ||
173 | end | ||
174 | end | ||
175 | if table.getn(arg) > 0 then -- chop last comma | ||
176 | parms = string.sub(parms, 1, -2) | ||
177 | end | ||
178 | -- up level | ||
179 | llog:msg(ModuleName..OldName..parms..") {\n", llog.level) | ||
180 | llog.level = llog.level + 1 | ||
181 | -- display contents of expdesc | ||
182 | if SHOW_EXPDESC and table.getn(exps) > 0 then | ||
183 | for i,v in ipairs(exps) do | ||
184 | parms = "k:'"..v.k.."'," | ||
185 | if v.info then parms = parms.."info:"..v.info.."," end | ||
186 | if v.aux then parms = parms.."aux:"..v.aux.."," end | ||
187 | if v.t then parms = parms.."t:"..v.t.."," end | ||
188 | if v.f then parms = parms.."f:"..v.f.."," end | ||
189 | parms = string.sub(parms, 1, -2) | ||
190 | llog:msg("exp"..i.."("..parms..")\n", llog.level) | ||
191 | end | ||
192 | end | ||
193 | -- original function called here... | ||
194 | local retval = {self[NewName](self, unpack(arg))} | ||
195 | -- format return values | ||
196 | local rets = " = " | ||
197 | for i,v in ipairs(retval) do | ||
198 | if type(v) == "number" then rets = rets..v.."," | ||
199 | elseif type(v) == "string" then rets = rets.."'"..v.."'," | ||
200 | elseif type(v) == "boolean" then rets = rets..tostring(v).."," | ||
201 | else rets = rets..type(v).."," | ||
202 | end | ||
203 | end | ||
204 | if table.getn(retval) > 0 then -- chop last comma | ||
205 | rets = string.sub(rets, 1, -2) | ||
206 | else | ||
207 | rets = "" | ||
208 | end | ||
209 | -- down level | ||
210 | llog.level = llog.level - 1 | ||
211 | llog:msg("} "..ModuleName..OldName..rets.."\n", llog.level) | ||
212 | return unpack(retval) | ||
213 | end--function | ||
214 | ---------------------------------------------------------- | ||
215 | --print("patched "..OldName) | ||
216 | end--if | ||
217 | end--for | ||
218 | end | ||
219 | |||
220 | ------------------------------------------------------------------------ | ||
221 | -- testing here | ||
222 | -- * allow/deny works a bit like a somewhat similar Apache syntax | ||
223 | -- * e.g. to show only function 'lex' and 'save' -> allow={"lex","save",} | ||
224 | -- to not show function 'save_and_next' -> deny={"save_and_next",} | ||
225 | -- * you can't do both allow and deny at the same time | ||
226 | ------------------------------------------------------------------------ | ||
227 | |||
228 | -- select the file or stream to output to | ||
229 | --llog:init("calls.log") | ||
230 | llog:init("stdout") | ||
231 | |||
232 | -- select modules to trace | ||
233 | llog:calltrace{module=luaX, modulename="luaX", allow={"lex"} } | ||
234 | -- here we trace only the main lex() function, to avoid showing | ||
235 | -- too many lexer calls; we want to focus on luaY and luaK | ||
236 | llog:calltrace{module=luaY, modulename="luaY", deny={"growvector"} } | ||
237 | -- growvector() is just a limit checker in Yueliang, so drop it | ||
238 | -- to simplify the output log | ||
239 | llog:calltrace{module=luaK, modulename="luaK"} | ||
240 | --llog:calltrace{module=luaU, modulename="luaU"} | ||
241 | |||
242 | -- select input stream | ||
243 | local zio = luaZ:init(luaZ:make_getS("local a = 1"), nil, "=string") | ||
244 | --local zio = luaZ:init(luaZ:make_getF("sample.lua"), nil, "@sample.lua") | ||
245 | |||
246 | -- compile the source | ||
247 | local Func = luaY:parser(LuaState, zio, nil) | ||
248 | |||
249 | -- write binary chunk | ||
250 | local Writer, Buff = luaU:make_setF("call_graph.out") | ||
251 | luaU:dump(LuaState, Func, Writer, Buff) | ||
252 | |||
253 | llog:exit() | ||
254 | --end | ||
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log new file mode 100644 index 0000000..c163f6c --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/calls.log | |||
@@ -0,0 +1,152 @@ | |||
1 | |||
2 | -- start of log -- | ||
3 | |||
4 | luaY:parser (table,table) { | ||
5 | luaY:open_func (table,table) { | ||
6 | luaY:newproto (table) { | ||
7 | } luaY:newproto = table | ||
8 | } luaY:open_func | ||
9 | luaY:next (table) { | ||
10 | luaX:lex (table,table) { | ||
11 | } luaX:lex = 'TK_LOCAL' | ||
12 | } luaY:next | ||
13 | luaY:chunk (table) { | ||
14 | luaY:enterlevel (table) { | ||
15 | } luaY:enterlevel | ||
16 | luaY:block_follow ('TK_LOCAL') { | ||
17 | } luaY:block_follow = false | ||
18 | luaY:statement (table) { | ||
19 | luaY:next (table) { | ||
20 | luaX:lex (table,table) { | ||
21 | } luaX:lex = 'TK_NAME' | ||
22 | } luaY:next | ||
23 | luaY:testnext (table,'TK_FUNCTION') { | ||
24 | } luaY:testnext = false | ||
25 | luaY:localstat (table) { | ||
26 | luaY:str_checkname (table) { | ||
27 | luaY:check_condition (table,true,'<name> expected') { | ||
28 | } luaY:check_condition | ||
29 | luaY:next (table) { | ||
30 | luaX:lex (table,table) { | ||
31 | } luaX:lex = '=' | ||
32 | } luaY:next | ||
33 | } luaY:str_checkname = 'a' | ||
34 | luaY:new_localvar (table,'a',0) { | ||
35 | luaY:registerlocalvar (table,'a') { | ||
36 | luaY:growvector (table,table,0,0) { | ||
37 | } luaY:growvector | ||
38 | } luaY:registerlocalvar = 0 | ||
39 | } luaY:new_localvar | ||
40 | luaY:testnext (table,',') { | ||
41 | } luaY:testnext = false | ||
42 | luaY:testnext (table,'=') { | ||
43 | luaY:next (table) { | ||
44 | luaX:lex (table,table) { | ||
45 | } luaX:lex = 'TK_NUMBER' | ||
46 | } luaY:next | ||
47 | } luaY:testnext = true | ||
48 | luaY:explist1 (table,table) { | ||
49 | luaY:expr (table,table) { | ||
50 | luaY:subexpr (table,table,-1) { | ||
51 | luaY:enterlevel (table) { | ||
52 | } luaY:enterlevel | ||
53 | luaY:getunopr ('TK_NUMBER') { | ||
54 | } luaY:getunopr = 'OPR_NOUNOPR' | ||
55 | luaY:simpleexp (table,table) { | ||
56 | luaK:numberK (table,1) { | ||
57 | luaK:setnvalue (table,1) { | ||
58 | } luaK:setnvalue | ||
59 | luaK:addk (table,table,table) { | ||
60 | luaK:ttisnumber ) { | ||
61 | } luaK:ttisnumber = false | ||
62 | luaY:growvector (table,table,0,0) { | ||
63 | } luaY:growvector | ||
64 | luaK:setnvalue (table,0) { | ||
65 | } luaK:setnvalue | ||
66 | } luaK:addk = 0 | ||
67 | } luaK:numberK = 0 | ||
68 | luaY:init_exp (table,'VK',0) { | ||
69 | } luaY:init_exp | ||
70 | luaY:next (table) { | ||
71 | luaX:lex (table,table) { | ||
72 | } luaX:lex = 'TK_EOS' | ||
73 | } luaY:next | ||
74 | } luaY:simpleexp | ||
75 | luaY:getbinopr ('TK_EOS') { | ||
76 | } luaY:getbinopr = 'OPR_NOBINOPR' | ||
77 | luaY:leavelevel (table) { | ||
78 | } luaY:leavelevel | ||
79 | } luaY:subexpr = 'OPR_NOBINOPR' | ||
80 | } luaY:expr | ||
81 | luaY:testnext (table,',') { | ||
82 | } luaY:testnext = false | ||
83 | } luaY:explist1 = 1 | ||
84 | luaY:adjust_assign (table,1,1,table) { | ||
85 | luaK:exp2nextreg (table,table) { | ||
86 | luaK:dischargevars (table,table) { | ||
87 | } luaK:dischargevars | ||
88 | luaK:freeexp (table,table) { | ||
89 | } luaK:freeexp | ||
90 | luaK:reserveregs (table,1) { | ||
91 | luaK:checkstack (table,1) { | ||
92 | } luaK:checkstack | ||
93 | } luaK:reserveregs | ||
94 | luaK:exp2reg (table,table,0) { | ||
95 | luaK:discharge2reg (table,table,0) { | ||
96 | luaK:dischargevars (table,table) { | ||
97 | } luaK:dischargevars | ||
98 | luaK:codeABx (table,'OP_LOADK',0,0) { | ||
99 | luaK:code (table,table,1) { | ||
100 | luaK:dischargejpc (table) { | ||
101 | luaK:patchlistaux (table,-1,0,255,0,255,0) { | ||
102 | } luaK:patchlistaux | ||
103 | } luaK:dischargejpc | ||
104 | luaY:growvector (table,table,0,0) { | ||
105 | } luaY:growvector | ||
106 | luaY:growvector (table,table,0,0) { | ||
107 | } luaY:growvector | ||
108 | } luaK:code = 0 | ||
109 | } luaK:codeABx = 0 | ||
110 | } luaK:discharge2reg | ||
111 | luaK:hasjumps (table) { | ||
112 | } luaK:hasjumps = false | ||
113 | } luaK:exp2reg | ||
114 | } luaK:exp2nextreg | ||
115 | } luaY:adjust_assign | ||
116 | luaY:adjustlocalvars (table,1) { | ||
117 | luaY:getlocvar (table,0) { | ||
118 | } luaY:getlocvar = table | ||
119 | } luaY:adjustlocalvars | ||
120 | } luaY:localstat | ||
121 | } luaY:statement = false | ||
122 | luaY:testnext (table,';') { | ||
123 | } luaY:testnext = false | ||
124 | luaY:block_follow ('TK_EOS') { | ||
125 | } luaY:block_follow = true | ||
126 | luaY:leavelevel (table) { | ||
127 | } luaY:leavelevel | ||
128 | } luaY:chunk | ||
129 | luaY:check_condition (table,true,'<eof> expected') { | ||
130 | } luaY:check_condition | ||
131 | luaY:close_func (table) { | ||
132 | luaY:removevars (table,0) { | ||
133 | luaY:getlocvar (table,0) { | ||
134 | } luaY:getlocvar = table | ||
135 | } luaY:removevars | ||
136 | luaK:codeABC (table,'OP_RETURN',0,1,0) { | ||
137 | luaK:code (table,table,1) { | ||
138 | luaK:dischargejpc (table) { | ||
139 | luaK:patchlistaux (table,-1,1,255,1,255,1) { | ||
140 | } luaK:patchlistaux | ||
141 | } luaK:dischargejpc | ||
142 | luaY:growvector (table,table,1,0) { | ||
143 | } luaY:growvector | ||
144 | luaY:growvector (table,table,1,0) { | ||
145 | } luaY:growvector | ||
146 | } luaK:code = 1 | ||
147 | } luaK:codeABC = 1 | ||
148 | } luaY:close_func | ||
149 | } luaY:parser = table | ||
150 | |||
151 | -- end of log -- | ||
152 | |||
diff --git a/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua new file mode 100644 index 0000000..519cd4c --- /dev/null +++ b/LuaSL/testLua/yueliang-0.4.1/orig-5.0.3/tools/sample_expr.lua | |||
@@ -0,0 +1,195 @@ | |||
1 | --[[-------------------------------------------------------------------- | ||
2 | |||
3 | sample_expr.lua | ||
4 | Stand-alone expression parsing demonstrator. | ||
5 | This file is part of Yueliang. | ||
6 | |||
7 | Copyright (c) 2005 Kein-Hong Man <khman@users.sf.net> | ||
8 | The COPYRIGHT file describes the conditions | ||
9 | under which this software may be distributed. | ||
10 | |||
11 | See the ChangeLog for more information. | ||
12 | |||
13 | ----------------------------------------------------------------------]] | ||
14 | |||
15 | --[[-------------------------------------------------------------------- | ||
16 | -- Notes: | ||
17 | -- * this is an interactive demonstrator for implementing expression | ||
18 | -- parsing in ChunkBake, a Lua assembler | ||
19 | -- * evaluation is immediate, and a result is immediately generated | ||
20 | ----------------------------------------------------------------------]] | ||
21 | |||
22 | require("../lzio.lua") | ||
23 | require("../llex.lua") | ||
24 | luaX:init() | ||
25 | |||
26 | ------------------------------------------------------------------------ | ||
27 | -- expression parser | ||
28 | ------------------------------------------------------------------------ | ||
29 | |||
30 | expr = {} | ||
31 | |||
32 | expr.unop = { | ||
33 | ["TK_NOT"] = true, | ||
34 | ["-"] = true, | ||
35 | } | ||
36 | expr.binop = { | ||
37 | ["^"] = 10, | ||
38 | ["*"] = 7, | ||
39 | ["/"] = 7, | ||
40 | ["+"] = 6, | ||
41 | ["-"] = 6, | ||
42 | ["TK_CONCAT"] = 5, | ||
43 | ["TK_NE"] = 3, | ||
44 | ["TK_EQ"] = 3, | ||
45 | ["<"] = 3, | ||
46 | ["TK_LE"] = 3, | ||
47 | [">"] = 3, | ||
48 | ["TK_GE"] = 3, | ||
49 | ["TK_AND"] = 2, | ||
50 | ["TK_OR"] = 1, | ||
51 | } | ||
52 | expr.binop_r = { | ||
53 | ["^"] = 9, | ||
54 | ["*"] = 7, | ||
55 | ["/"] = 7, | ||
56 | ["+"] = 6, | ||
57 | ["-"] = 6, | ||
58 | ["TK_CONCAT"] = 4, | ||
59 | ["TK_NE"] = 3, | ||
60 | ["TK_EQ"] = 3, | ||
61 | ["<"] = 3, | ||
62 | ["TK_LE"] = 3, | ||
63 | [">"] = 3, | ||
64 | ["TK_GE"] = 3, | ||
65 | ["TK_AND"] = 2, | ||
66 | ["TK_OR"] = 1, | ||
67 | } | ||
68 | |||
69 | function expr:parse(str) | ||
70 | self.LS = {} | ||
71 | self.L = {} | ||
72 | self.z = luaZ:init(luaZ:make_getS(str), nil, "=string") | ||
73 | luaX:setinput(self.L, self.LS, self.z, self.z.name) | ||
74 | self:token() | ||
75 | local v = self:expr() | ||
76 | if self.tok ~= "TK_EOS" then | ||
77 | io.stderr:write("parse error: some tokens unparsed\n") | ||
78 | end | ||
79 | return v | ||
80 | end | ||
81 | |||
82 | function expr:token() | ||
83 | self.tok = luaX:lex(self.LS, self.LS.t) | ||
84 | self.seminfo = self.LS.t.seminfo | ||
85 | return self.tok | ||
86 | end | ||
87 | |||
88 | function expr:simpleexpr() | ||
89 | local tok = self.tok | ||
90 | if tok == "TK_NIL" then | ||
91 | self:token() | ||
92 | return nil | ||
93 | elseif tok == "TK_TRUE" then | ||
94 | self:token() | ||
95 | return true | ||
96 | elseif tok == "TK_FALSE" then | ||
97 | self:token() | ||
98 | return false | ||
99 | elseif tok == "TK_NUMBER" or tok == "TK_STRING" then | ||
100 | self:token() | ||
101 | return self.seminfo | ||
102 | elseif tok == "(" then | ||
103 | self:token() | ||
104 | local v = self:expr() | ||
105 | if self.tok ~= ")" then | ||
106 | io.stderr:write("parse error: expecting ')' to delimit\n") | ||
107 | else | ||
108 | self:token() | ||
109 | return v | ||
110 | end | ||
111 | end | ||
112 | self:token() | ||
113 | io.stderr:write("parse error: "..tok.." encountered, substituting nil\n") | ||
114 | return nil | ||
115 | end | ||
116 | |||
117 | function expr:subexpr(prev_op) | ||
118 | local v, op | ||
119 | if self.unop[self.tok] then | ||
120 | op = self.tok | ||
121 | self:token() | ||
122 | v = self:subexpr(8) | ||
123 | if op == "TK_NOT" then | ||
124 | v = not v | ||
125 | else-- op == "-" then | ||
126 | v = -v | ||
127 | end | ||
128 | else | ||
129 | v = self:simpleexpr() | ||
130 | end | ||
131 | op = self.tok | ||
132 | if self.binop[op] then | ||
133 | while self.binop[op] and self.binop[op] > prev_op do | ||
134 | self:token() | ||
135 | local v2, next_op = self:subexpr(self.binop_r[op]) | ||
136 | if op == "^" then | ||
137 | v = v ^ v2 | ||
138 | elseif op == "*" then | ||
139 | v = v * v2 | ||
140 | elseif op == "/" then | ||
141 | v = v / v2 | ||
142 | elseif op == "+" then | ||
143 | v = v + v2 | ||
144 | elseif op == "-" then | ||
145 | v = v - v2 | ||
146 | elseif op == "TK_CONCAT" then | ||
147 | v = v .. v2 | ||
148 | elseif op == "TK_NE" then | ||
149 | v = v ~= v2 | ||
150 | elseif op == "TK_EQ" then | ||
151 | v = v == v2 | ||
152 | elseif op == "<" then | ||
153 | v = v < v2 | ||
154 | elseif op == "TK_LE" then | ||
155 | v = v <= v2 | ||
156 | elseif op == ">" then | ||
157 | v = v > v2 | ||
158 | elseif op == "TK_GE" then | ||
159 | v = v >= v2 | ||
160 | elseif op == "TK_AND" then | ||
161 | v = v and v2 | ||
162 | else-- op == "TK_OR" then | ||
163 | v = v or v2 | ||
164 | end | ||
165 | op = next_op | ||
166 | end | ||
167 | end | ||
168 | return v, op | ||
169 | end | ||
170 | |||
171 | function expr:expr() | ||
172 | return self:subexpr(-1) | ||
173 | end | ||
174 | |||
175 | ------------------------------------------------------------------------ | ||
176 | -- interactive test code | ||
177 | ------------------------------------------------------------------------ | ||
178 | |||
179 | io.stdout:write([[ | ||
180 | Lua-style expression parsing demonstrator. | ||
181 | Type 'exit' or 'quit' at the prompt to terminate session. | ||
182 | ]]) | ||
183 | local done = false | ||
184 | while not done do | ||
185 | io.stdout:write(":>") | ||
186 | io.stdout:flush() | ||
187 | local l = io.stdin:read("*l") | ||
188 | if l == nil or (l == "exit" or l == "quit" and not prevline) then | ||
189 | done = true | ||
190 | else | ||
191 | local v = tostring(expr:parse(l)) | ||
192 | io.stdout:write(v, "\n") | ||
193 | end | ||
194 | end--while | ||
195 | --end | ||