User:XFire35/auo.lua
Jump to navigation
Jump to search
#!/usr/bin/env lua
--[[
Copyright (c) 2009, Curt Strangward
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
]]--
_s = {} -- Stack
_v = {} -- Variable Stack
_j = {} -- Jump Stack
_c = {} -- Code Stack
_t = {} -- Temporary Array
_l = {} -- Loop Array - Used in Control Flow Statements
---------------------------------------------------------------------------------------------
-- Language Support Functions
function print(text) -- Modifies lua's print to make it look nicer
if text ~= nil then io.write ( ":: "..text.."\n" );
else end
end
function pA(array) -- Prints the array
for k, v in pairs(array) do
print(k..": "..array[k]);
end
end
function c_v(var) -- Checks variable
if _v[var] then
if type(_v[var]) == "string" then
return("'".._v[var].."'")
else
return(_v[var])
end
else
print("Unidentified Value: "..var)
end
end
function c_vB(var) -- Checks variable B version
if _v[var] then
return(_v[var])
else
print("Unidentified Value: "..var)
end
end
function v_m(_cT)
if string.match(_cT, "%$[%w+%_]+") then
_cT = string.gsub(_cT, "%$([%w+%_]+)", c_v)
end
return(_cT)
end
---------------------------------------------------------------------------------------------
-- Language's Stack Functions
function s_push(value) -- Push value to _s
table.insert(_s, value)
end
function s_pop() -- Retrieve top _s item
if table.getn(_s) == 0 then return ("0")
else
return(table.remove(_s))
end
end
function s_del() -- Remove top item from stack
s_pop()
end
function s_mer() -- Merge top two items on stack
local a, b = s_pop(), s_pop()
s_push(tostring(a)..tostring(b))
end
function s_dup() -- Duplicate top item on _s
if table.getn(_s) == 0 then e("Stack","0")
else
local a = s_pop()
s_push(a); s_push(a);
end
end
function s_exh(value) -- Exchanges top two _s items
local a, b = s_pop(), s_pop()
s_push(a); s_push(b);
end
function s_clear() -- Clear the stack
_s = {}
end
---------------------------------------------------------------------------------------------
-- Language's Functions
function m_add(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
s_push(x+y)
else print("Malformed Variables") end
end
function m_sub(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
s_push(x-y)
else print("Malformed Variables") end
end
function m_mul(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
s_push(x*y)
else print("Malformed Variables") end
end
function m_div(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
s_push(x/y)
else print("Malformed Variables") end
end
function q_equ(x,y)
if x ~= "" or nil and y ~= "" or nil then
if x == y then s_push('true') else s_push('false') end
end
end
function q_neq(x,y)
if x ~= "" or nil and y ~= "" or nil then
if x ~= y then s_push('true') else s_push('false') end
end
end
function q_lss(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
if x < y then s_push('true') else s_push('false') end
else print("Malformed Variables") end
end
function q_els(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
if x <= y then s_push('true') else s_push('false') end
else print("Malformed Variables") end
end
function q_grt(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
if x > y then s_push('true') else s_push('false') end
else print("Malformed Variables") end
end
function q_egr(x,y)
local x, y = tonumber(x), tonumber(y)
if type(x) == "number" and type(y) == "number" then
if x >= y then s_push('true') else s_push('false') end
else print("Malformed Variables") end
end
function t_len(x)
if x ~= "" or nil then
s_push(string.len(tostring(x)))
end
end
function t_add(x,y)
s_push(x..y)
end
function t_div(x,n)
local _t, _t2, n = {}, {}, tonumber(n)
for m in string.gfind(x, "[%w%p%s]") do
table.insert(_t, m)
end
if n > table.getn(_t) then
print("Error: Value exceeds string length")
else
for i = n, table.getn(_t),1 do
table.insert(_t2, _t[i])
_t[i] = nil
end
_t, _t2 = table.concat(_t,""), table.concat(_t2,"")
s_push(_t); s_push(_t2)
end
end
function i_prt(text)
if text ~= nil then io.write ( ":> "..text.."\n" );
else end
end
---------------------------------------------------------------------------------------------
-- Main Language Parser, Causes everything to be run
function process(t)
for token = 1, table.getn(t) do
local _cT = t[token]
-- Conditional Statements
-- c.i:[%true],[%false] > q.g:$x,10
if string.match(_cT, "c%.i%:%[%%([%w%_]+)%],%[%%([%w%_]+)%][%s]*%>[%s]*%a%.%a%:([%w%p]+)%,([%w%p]+)") then
_cT = string.gsub(_cT, "[%w%p%s]+(%a%.%a%:[%w%p]+%,[%w%p]+)", function(w) table.insert(_l,w); process(_l) end)
_l = {}
if s_pop() == "true" then
_cT = string.gsub(_cT, "c%.i%:%[(%%[%w%_]+)%][%w%p%s]+", function(w) table.insert(_l,w); process(_l) end)
elseif s_pop() == "false" then
_cT = string.gsub(_cT, "c%.i%:[%w%p%s]+,%[(%%[%w%_]+)%][%w%p%s]", function(w) table.insert(_l,w); process(_l) end)
end
_l = {}
-- c.f:[update],[%body] > q.g:$x,10
elseif string.match(_cT, "c%.f%:%[%a%.%a%:$[%w%_]+%,[%w%p]+%],%[%%[%w%_]+%][%s]*%>[%s]*%a%.%a%:[%w%p]+%,[%w%p]+") then
local var = ""
_cT = string.gsub(_cT, "[%w%p%s]+%>[%s]*(%a%.%a%:[%w%p]+%,[%w%p]+)", function(w) table.insert(_l,w); end) -- Argument
_cT = string.gsub(_cT, "c%.f%:[%w%p%s]+,%[(%%[%w%_]+)%][%w%p%s]+", function(w) table.insert(_l,w); end) -- Body
_cT = string.gsub(_cT, "c%.f%:%[(%a%.%a%:$[%w%_]+%,[%w%p]+)%][%w%p]+", function(w) table.insert(_l,w); end) -- Change
_cT = string.gsub(_cT, "c%.f%:%[%a%.%a%:$([%w%_]+)%,[%w%p]+%][%w%p%s]", function(w) if _v[w] then var = w end end)
while true do
process(_l)
_v[var] = s_pop()
if s_pop() == "false" then break end
end
_l = {}
-- c.w:[update],[%body] > q.g:$x,10
elseif string.match(_cT, "c%.w%:%[%%([%w%_]+)%][%s]*%>[%s]*%a%.%a%:([%w%p]+)%,([%w%p]+)") then
_cT = string.gsub(_cT, "[%w%p%s]+%>[%s]*(%a%.%a%:[%w%p]+%,[%w%p]+)", function(w) table.insert(_l,w) end)
_cT = string.gsub(_cT, "c%.w%:%[(%%[%w%_]+)%][%w%p%s]", function(w) table.insert(_l,w) end)
while true do
process(_l)
if s_pop() == "false" then break end
end
_l = {}
-- %foo -- Runs function 'foo'
elseif string.match(_cT, "^%%([%w%_]+)") then
_cT = string.gsub(_cT, "%%([%w%_]+)", function(w) if _j[w] then process(_j[w]); end end)
end
-- Math Functions
-- m.a:x,y - Add x and y
if string.match(_cT, "m%.a%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "m%.a%:(%w+),(%w+)", m_add)
-- m.s:x,y - Add x and y
elseif string.match(_cT, "m%.s%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "m%.s%:(%w+),(%w+)", m_sub)
-- m.m:x,y - Add x and y
elseif string.match(_cT, "m%.m%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "m%.m%:(%w+),(%w+)", m_mul)
-- m.d:x,y - Add x and y
elseif string.match(_cT, "m%.d%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "m%.d%:(%w+),(%w+)", m_div)
-- Comparison Functions
-- q.e:x,y Equal?
elseif string.match(_cT, "q%.e%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.e%:([%w%p%s]+),([%w%p%s]+)", q_equ)
-- q.n:x,y Not equal?
elseif string.match(_cT, "q%.n%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.n%:%'?([%w%p%s]+)%'?,%'?([%w%p%s]+)%'?", q_neq)
-- q.l:x,y x less than y
elseif string.match(_cT, "q%.l%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.l%:(%w+),(%w+)", q_lss)
-- q.s:x,y x less than, equal to y
elseif string.match(_cT, "q%.s%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.a%:(%w+),(%w+)", q_els)
-- q.g:x,y x greater than y
elseif string.match(_cT, "q%.g%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.g%:(%w+),(%w+)", q_grt)
-- q.r:x,y x greater than, equal to y
elseif string.match(_cT, "q%.r%:(%-?[%$%_%w%.?]+),(%-?[%$%_%w%.?]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "q%.r%:(%w+),(%w+)", q_egr)
end
-- String Functions
-- s.l:x - Length of string x
if string.match(_cT, "s%.l%:([%w%p]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "s%.l%:%'([%w%s%p]+)%'", t_len)
-- s.a:x,y - Add strings x and y together
elseif string.match(_cT, "s%.a%:([%w%p]+),([%w%p]+)") then
_cT = v_m(_cT)
_cT = string.gsub(_cT, "s%.a%:%'([%w%s%p]+)%','([%w%s%p]+)%'", t_add)
-- s.s:x,n - Split string x at position n
elseif string.match(_cT, "s%.s%:([%w%p]+),([%w%p]+)") then
_cT = v_m(_cT)
if string.match(_cT, "s%.s%:%'([%w%s%p]+)%',([%d]+)") then
_cT = string.gsub(_cT, "s%.s%:%'([%w%s%p]+)%',([%d]+)", function(w,x) t_div(w,x) end)
end
end
-- Stack Functions
-- @ Pushes value to stack
if string.match(_cT, "%'?([%$%_%w]+)%'?[%s]*%>[%s]*%@") then
_cT = v_m(_cT)
if string.match(_cT, "(%-?[%d%.?]+)[%s]*%>[%s]*%@") then
_cT = string.gsub(_cT, "(%-?[%d%.?]+)[%s]*%>[%s]*%@", function(w) s_push(tonumber(w)) end)
elseif string.match(_cT, "%'([%w%s%p]+)%'[%s]*%>[%s]*%@") then
_cT = string.gsub(_cT, "%'([%w%s%p]+)%'[%s]*%>[%s]*%@", function(w) s_push(tostring(w)) end)
end
-- <@ Pops value from stack
elseif string.match(_cT, "%<%@") then
local var = s_pop()
if type(var) == "number" then _cT = string.gsub(_cT, "%<%@", var)
else _cT = string.gsub(_cT, "%<%@", "'"..var.."'") end
-- -@ Disgards top item on stack
elseif string.match(_cT, "%-%@") then
s_del()
-- *@ Duplicate top item on stack
elseif string.match(_cT, "%*%@") then
s_dup()
-- +@ Merges the top two items on stack
elseif string.match(_cT, "%+%@") then
s_mer()
-- ~@ Disgards top item on stack
elseif string.match(_cT, "%~%@") then
s_exh()
-- /@ Clears the stack
elseif string.match(_cT, "%@") then
s_clear()
end
-- Variable Declaration Functions
-- 5 > $a
if string.match(_cT, "(%-?[%d%.?]+)[%s]*%>[%s]*%$([%w%_]+)") then
_cT = string.gsub(_cT, "(%-?[%d%.?]+)[%s]*%>[%s]*%$([%w%_]+)", function(w,x) _v[x] = tonumber(w) end)
-- 'foo' > $bar
elseif string.match(_cT, "%'([%w%s%p]+)%'[%s]*%>[%s]*%$([%w%_]+)") then
_cT = string.gsub(_cT, "%'([%w%s%p]+)%'[%s]*%>[%s]*%$([%w%_]+)", function(w,x) _v[x] = tostring(w) end)
-- $nil > $foo, Clears value $foo
elseif string.match(_cT, "%$nil[%s]*%>[%s]*%$([%w%_]+)") then
_cT = string.gsub(_cT, "%$nil[%s]*%>[%s]*%$([%w%_]+)", function(w) _v[w] = nil end)
-- $foo > $bar
elseif string.match(_cT, "%$([%w%_]+)[%s]*%>[%s]*%$([%w%_]+)") then
_cT = string.gsub(_cT, "%$([%w%_]+)[%s]*%>[%s]*%$([%w%_]+)", function(w,x) if _v[w] then _v[x] = c_v(w) end end)
end
-- Input/Output Functions
-- i.o:['Message'] -- Writes message
if string.match(_cT, "i%.o%:%[%'[%w+%s+%p+]+%'%]") then
if string.match(_cT, "%$[%w+%_]+") then
_cT = string.gsub(_cT, "%$([%w+%_]+)", c_vB)
end
_cT = string.gsub(_cT, "i%.o%:%[%'([%w+%s+%p+]+)%'%]", i_prt)
-- i.i:$var -- User input >$var
elseif string.match(_cT, "i%.i%:$([%w%_]+)") then
io.write ( " > " )
local input = io.stdin:read"*l"
if input ~= "" then
_cT = string.gsub(_cT, "i%.i%:$([%w%_]+)", function(w) _v[w] = tostring(input) end)
else
_cT = string.gsub(_cT, "i%.i%:$([%w%_]+)", function(w) _v[w] = '' end)
end
-- i.r:['file'] -- Run File
elseif string.match(_cT, "i%.r%:%[%'[%w+%s+%p+]+%'%]") then
_cT = v_m(_cT)
local input = ""
_cT = string.gsub(_cT, "i%.r%:%[%'([%w+%s+%p+]+)%'%]", function (w) input = w end)
if io.open (input, "r") then
local file = io.open(input, "r")
local str = file:read("*a")
for match in string.gfind(str, "%s*([^\n]*%S)") do
if string.match(match, "%#[%s+%w+%p+]+") then
match = string.gsub(match, "%#[%s+%w+%p+]+", "")
end
if match == "" then match = nil
else
table.insert(_t,match)
end
end
end
jump_rec(_t);
process(_t)
_t = {}
end
end
end
---------------------------------------------------------------------------------------------
-- Jump Recorder:
-- Inserts into a table what code is used for a 'jump'
function jump_rec(t)
for i = 1, table.getn(t) do
_cT = t[i]
if string.match(_cT, "%%([%w%_]+)%:[%s]*%{") then
local title = ""
_cT = string.gsub(_cT, "%%([%w%_]+)%:[%s]*%{", function(w) title = w end)
if string.match(_cT, "%%([%w%_]+)%:[%s]*%{") then
t[i] = ""
local a = i + 1
local code = {}
while true do
_cA = t[a]
if string.match(_cA, "^%}") then
t[a] = ""
break
else
table.insert(code, _cA)
t[a] = ""
end
a = a + 1
end
_j[title] = code
end
end
end
end
---------------------------------------------------------------------------------------------
-- Splits the source into table arrrays
function tokeniser(line)
for match in string.gfind(line, "%s*([^\n]*%S)") do
if string.match(match, "%#[%s+%w+%p+]+") then
match = string.gsub(match, "%#[%s+%w+%p+]+", "")
end
if match == "" then match = nil
else
table.insert(_c,match)
end
end
jump_rec(_c);
end
---------------------------------------------------------------------------------------------
-- Main Routine
function main() -- Main program loop
io.write ( ">> " );
local input = io.stdin:read"*l"
if input == "quit" then os.exit() end
if input ~= "" or nil then
tokeniser(input); -- Ensure input is not blank
process(_c);
_c = {};
_l = {};
_t = {};
end
main();
end
io.write(":: Auo \n");
main()