This commit is contained in:
jack-fractal
2013-11-17 16:30:42 -05:00
199 changed files with 16877 additions and 14848 deletions

View File

@@ -0,0 +1,497 @@
//Structured Datum Query Language. Basically SQL meets BYOND objects.
//Note: For use in BS12, need text_starts_with proc, and to modify the action on select to use BS12's object edit command(s).
/client/proc/SDQL_query(query_text as message)
set category = "Admin"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
var/list/query_list = SDQL_tokenize(query_text)
if(query_list.len < 2)
if(query_list.len > 0)
usr << "\red SDQL: Too few discrete tokens in query \"[query_text]\". Please check your syntax and try again."
return
if(!(lowertext(query_list[1]) in list("select", "delete", "update")))
usr << "\red SDQL: Unknown query type: \"[query_list[1]]\" in query \"[query_text]\". Please check your syntax and try again."
return
var/list/types = list()
var/i
for(i = 2; i <= query_list.len; i += 2)
types += query_list[i]
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
break
i++
var/list/from = list()
if(i <= query_list.len)
if(lowertext(query_list[i]) in list("from", "in"))
for(i++; i <= query_list.len; i += 2)
from += query_list[i]
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
break
i++
if(from.len < 1)
from += "world"
var/list/set_vars = list()
if(lowertext(query_list[1]) == "update")
if(i <= query_list.len && lowertext(query_list[i]) == "set")
for(i++; i <= query_list.len; i++)
if(i + 2 <= query_list.len && query_list[i + 1] == "=")
set_vars += query_list[i]
set_vars[query_list[i]] = query_list[i + 2]
else
usr << "\red SDQL: Invalid set parameter in query \"[query_text]\". Please check your syntax and try again."
return
i += 3
if(i >= query_list.len || query_list[i] != ",")
break
if(set_vars.len < 1)
usr << "\red SDQL: Invalid or missing set in query \"[query_text]\". Please check your syntax and try again."
return
var/list/where = list()
if(i <= query_list.len && lowertext(query_list[i]) == "where")
where = query_list.Copy(i + 1)
var/list/from_objs = list()
if("world" in from)
from_objs += world
else
for(var/f in from)
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
from_objs += locate(copytext(f, 2, length(f)))
else if(copytext(f, 1, 2) != "/")
from_objs += locate(f)
else
var/f2 = text2path(f)
if(text_starts_with(f, "/mob"))
for(var/mob/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/space"))
for(var/turf/space/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/simulated"))
for(var/turf/simulated/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf/unsimulated"))
for(var/turf/unsimulated/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/turf"))
for(var/turf/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/area"))
for(var/area/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj/item"))
for(var/obj/item/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj/machinery"))
for(var/obj/machinery/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/obj"))
for(var/obj/m in world)
if(istype(m, f2))
from_objs += m
else if(text_starts_with(f, "/atom"))
for(var/atom/m in world)
if(istype(m, f2))
from_objs += m
/*
else
for(var/datum/m in world)
if(istype(m, f2))
from_objs += m
*/
var/list/objs = list()
for(var/from_obj in from_objs)
if("*" in types)
objs += from_obj:contents
else
for(var/f in types)
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
objs += locate(copytext(f, 2, length(f))) in from_obj
else if(copytext(f, 1, 2) != "/")
objs += locate(f) in from_obj
else
var/f2 = text2path(f)
if(text_starts_with(f, "/mob"))
for(var/mob/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/space"))
for(var/turf/space/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/simulated"))
for(var/turf/simulated/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf/unsimulated"))
for(var/turf/unsimulated/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/turf"))
for(var/turf/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/area"))
for(var/area/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj/item"))
for(var/obj/item/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj/machinery"))
for(var/obj/machinery/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/obj"))
for(var/obj/m in from_obj)
if(istype(m, f2))
objs += m
else if(text_starts_with(f, "/atom"))
for(var/atom/m in from_obj)
if(istype(m, f2))
objs += m
else
for(var/datum/m in from_obj)
if(istype(m, f2))
objs += m
for(var/datum/t in objs)
var/currently_false = 0
for(i = 1, i - 1 < where.len, i++)
var/v = where[i++]
var/compare_op = where[i++]
if(!(compare_op in list("==", "=", "<>", "<", ">", "<=", ">=", "!=")))
usr << "\red SDQL: Unknown comparison operator [compare_op] in where clause following [v] in query \"[query_text]\". Please check your syntax and try again."
return
var/j
for(j = i, j <= where.len, j++)
if(lowertext(where[j]) in list("and", "or", ";"))
break
if(!currently_false)
var/value = SDQL_text2value(t, v)
var/result = SDQL_evaluate(t, where.Copy(i, j))
switch(compare_op)
if("=", "==")
currently_false = !(value == result)
if("!=", "<>")
currently_false = !(value != result)
if("<")
currently_false = !(value < result)
if(">")
currently_false = !(value > result)
if("<=")
currently_false = !(value <= result)
if(">=")
currently_false = !(value >= result)
if(j > where.len || lowertext(where[j]) == ";")
break
else if(lowertext(where[j]) == "or")
if(currently_false)
currently_false = 0
else
break
i = j
if(currently_false)
objs -= t
usr << "\blue SQDL Query: [query_text]"
message_admins("[usr] executed SDQL query: \"[query_text]\".")
/*
for(var/t in types)
usr << "Type: [t]"
for(var/t in from)
usr << "From: [t]"
for(var/t in set_vars)
usr << "Set: [t] = [set_vars[t]]"
if(where.len)
var/where_str = ""
for(var/t in where)
where_str += "[t] "
usr << "Where: [where_str]"
usr << "From objects:"
for(var/datum/t in from_objs)
usr << t
usr << "Objects:"
for(var/datum/t in objs)
usr << t
*/
switch(lowertext(query_list[1]))
if("delete")
for(var/datum/t in objs)
del t
if("update")
for(var/datum/t in objs)
objs[t] = list()
for(var/v in set_vars)
if(v in t.vars)
objs[t][v] = SDQL_text2value(t, set_vars[v])
for(var/datum/t in objs)
for(var/v in objs[t])
t.vars[v] = objs[t][v]
if("select")
var/text = ""
for(var/datum/t in objs)
if(istype(t, /atom))
var/atom/a = t
if(a.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
else if(a.loc && a.loc.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
//text += "[t]<br>"
usr << browse(text, "window=sdql_result")
/client/Topic(href,href_list[],hsrc)
if(href_list["SDQL_select"])
debug_variables(locate(href_list["SDQL_select"]))
..()
/proc/SDQL_evaluate(datum/object, list/equation)
if(equation.len == 0)
return null
else if(equation.len == 1)
return SDQL_text2value(object, equation[1])
else if(equation[1] == "!")
return !SDQL_evaluate(object, equation.Copy(2))
else if(equation[1] == "-")
return -SDQL_evaluate(object, equation.Copy(2))
else
usr << "\red SDQL: Sorry, equations not yet supported :("
return null
/proc/SDQL_text2value(datum/object, text)
if(text2num(text) != null)
return text2num(text)
else if(text == "null")
return null
else if(copytext(text, 1, 2) == "'" || copytext(text, 1, 2) == "\"" )
return copytext(text, 2, length(text))
else if(copytext(text, 1, 2) == "/")
return text2path(text)
else
if(findtext(text, "."))
var/split = findtext(text, ".")
var/v = copytext(text, 1, split)
if((v in object.vars) && istype(object.vars[v], /datum))
return SDQL_text2value(object.vars[v], copytext(text, split + 1))
else
return null
else
if(text in object.vars)
return object.vars[text]
else
return null
/proc/text_starts_with(text, start)
if(copytext(text, 1, length(start) + 1) == start)
return 1
else
return 0
/proc/SDQL_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
var/list/single = list("(", ")", ",", "+", "-")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
"!" = list("", "="))
var/word = ""
var/list/query_list = list()
var/len = length(query_text)
for(var/i = 1, i <= len, i++)
var/char = copytext(query_text, i, i + 1)
if(char in whitespace)
if(word != "")
query_list += word
word = ""
else if(char in single)
if(word != "")
query_list += word
word = ""
query_list += char
else if(char in multi)
if(word != "")
query_list += word
word = ""
var/char2 = copytext(query_text, i + 1, i + 2)
if(char2 in multi[char])
query_list += "[char][char2]"
i++
else
query_list += char
else if(char == "'")
if(word != "")
usr << "\red SDQL: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "'"
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "'")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "'"
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]'"
word = ""
else if(char == "\"")
if(word != "")
usr << "\red SDQL: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "\""
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "\"")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "\""
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]\""
word = ""
else
word += char
if(word != "")
query_list += word
return query_list

View File

@@ -0,0 +1,426 @@
/client/proc/SDQL2_query(query_text as message)
set category = "Admin"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
if(!query_text || length(query_text) < 1)
return
//world << query_text
var/list/query_list = SDQL2_tokenize(query_text)
if(!query_list || query_list.len < 1)
return
var/list/query_tree = SDQL_parse(query_list)
if(query_tree.len < 1)
return
var/list/from_objs = list()
var/list/select_types = list()
switch(query_tree[1])
if("explain")
SDQL_testout(query_tree["explain"])
return
if("call")
if("on" in query_tree)
select_types = query_tree["on"]
else
return
if("select", "delete", "update")
select_types = query_tree[query_tree[1]]
from_objs = SDQL_from_objs(query_tree["from"])
var/list/objs = list()
for(var/type in select_types)
var/char = copytext(type, 1, 2)
if(char == "/" || char == "*")
for(var/from in from_objs)
objs += SDQL_get_all(type, from)
else if(char == "'" || char == "\"")
objs += locate(copytext(type, 2, length(type)))
if("where" in query_tree)
var/objs_temp = objs
objs = list()
for(var/datum/d in objs_temp)
if(SDQL_expression(d, query_tree["where"]))
objs += d
//usr << "Query: [query_text]"
message_admins("[usr] executed SDQL query: \"[query_text]\".")
switch(query_tree[1])
if("delete")
for(var/datum/d in objs)
del d
if("select")
var/text = ""
for(var/datum/t in objs)
if(istype(t, /atom))
var/atom/a = t
if(a.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
else if(a.loc && a.loc.x)
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
else
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
usr << browse(text, "window=SDQL-result")
if("update")
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/datum/d in objs)
var/list/vals = list()
for(var/v in set_list)
if(v in d.vars)
vals += v
vals[v] = SDQL_expression(d, set_list[v])
if(istype(d, /turf))
for(var/v in vals)
if(v == "x" || v == "y" || v == "z")
continue
d.vars[v] = vals[v]
else
for(var/v in vals)
d.vars[v] = vals[v]
/proc/SDQL_parse(list/query_list)
var/datum/SDQL_parser/parser = new(query_list)
var/list/query_tree = parser.parse()
del(parser)
return query_tree
/proc/SDQL_testout(list/query_tree, indent = 0)
var/spaces = ""
for(var/s = 0, s < indent, s++)
spaces += " "
for(var/item in query_tree)
if(istype(item, /list))
world << "[spaces]("
SDQL_testout(item, indent + 1)
world << "[spaces])"
else
world << "[spaces][item]"
if(!isnum(item) && query_tree[item])
if(istype(query_tree[item], /list))
world << "[spaces] ("
SDQL_testout(query_tree[item], indent + 2)
world << "[spaces] )"
else
world << "[spaces] [query_tree[item]]"
/proc/SDQL_from_objs(list/tree)
if("world" in tree)
return list(world)
var/list/out = list()
for(var/type in tree)
var/char = copytext(type, 1, 2)
if(char == "/")
out += SDQL_get_all(type, world)
else if(char == "'" || char == "\"")
out += locate(copytext(type, 2, length(type)))
return out
/proc/SDQL_get_all(type, location)
var/list/out = list()
if(type == "*")
for(var/datum/d in location)
out += d
return out
type = text2path(type)
if(ispath(type, /mob))
for(var/mob/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /turf))
for(var/turf/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /obj))
for(var/obj/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /area))
for(var/area/d in location)
if(istype(d, type))
out += d
else if(ispath(type, /atom))
for(var/atom/d in location)
if(istype(d, type))
out += d
else
for(var/datum/d in location)
if(istype(d, type))
out += d
return out
/proc/SDQL_expression(datum/object, list/expression, start = 1)
var/result = 0
var/val
for(var/i = start, i <= expression.len, i++)
var/op = ""
if(i > start)
op = expression[i]
i++
var/list/ret = SDQL_value(object, expression, i)
val = ret["val"]
i = ret["i"]
if(op != "")
switch(op)
if("+")
result += val
if("-")
result -= val
if("*")
result *= val
if("/")
result /= val
if("&")
result &= val
if("|")
result |= val
if("^")
result ^= val
if("=", "==")
result = (result == val)
if("!=", "<>")
result = (result != val)
if("<")
result = (result < val)
if("<=")
result = (result <= val)
if(">")
result = (result > val)
if(">=")
result = (result >= val)
if("and", "&&")
result = (result && val)
if("or", "||")
result = (result || val)
else
usr << "\red SDQL2: Unknown op [op]"
result = null
else
result = val
return result
/proc/SDQL_value(datum/object, list/expression, start = 1)
var/i = start
var/val = null
if(i > expression.len)
return list("val" = null, "i" = i)
if(istype(expression[i], /list))
val = SDQL_expression(object, expression[i])
else if(expression[i] == "!")
var/list/ret = SDQL_value(object, expression, i + 1)
val = !ret["val"]
i = ret["i"]
else if(expression[i] == "~")
var/list/ret = SDQL_value(object, expression, i + 1)
val = ~ret["val"]
i = ret["i"]
else if(expression[i] == "-")
var/list/ret = SDQL_value(object, expression, i + 1)
val = -ret["val"]
i = ret["i"]
else if(expression[i] == "null")
val = null
else if(isnum(expression[i]))
val = expression[i]
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
else
val = SDQL_var(object, expression, i)
i = expression.len
return list("val" = val, "i" = i)
/proc/SDQL_var(datum/object, list/expression, start = 1)
if(expression[start] in object.vars)
if(start < expression.len && expression[start + 1] == ".")
return SDQL_var(object.vars[expression[start]], expression[start + 2])
else
return object.vars[expression[start]]
else
return null
/proc/SDQL2_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
var/list/single = list("(", ")", ",", "+", "-", ".")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
">" = list("", "="),
"!" = list("", "="))
var/word = ""
var/list/query_list = list()
var/len = length(query_text)
for(var/i = 1, i <= len, i++)
var/char = copytext(query_text, i, i + 1)
if(char in whitespace)
if(word != "")
query_list += word
word = ""
else if(char in single)
if(word != "")
query_list += word
word = ""
query_list += char
else if(char in multi)
if(word != "")
query_list += word
word = ""
var/char2 = copytext(query_text, i + 1, i + 2)
if(char2 in multi[char])
query_list += "[char][char2]"
i++
else
query_list += char
else if(char == "'")
if(word != "")
usr << "\red SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "'"
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "'")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "'"
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]'"
word = ""
else if(char == "\"")
if(word != "")
usr << "\red SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". Please check your syntax, and try again."
return null
word = "\""
for(i++, i <= len, i++)
char = copytext(query_text, i, i + 1)
if(char == "\"")
if(copytext(query_text, i + 1, i + 2) == "'")
word += "\""
i++
else
break
else
word += char
if(i > len)
usr << "\red SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
return null
query_list += "[word]\""
word = ""
else
word += char
if(word != "")
query_list += word
return query_list

View File

@@ -0,0 +1,531 @@
//I'm pretty sure that this is a recursive [s]descent[/s] ascent parser.
//Spec
//////////
//
// query : select_query | delete_query | update_query | call_query | explain
// explain : 'EXPLAIN' query
//
// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
//
// select_list : select_item [',' select_list]
// select_item : '*' | select_function | object_type
// select_function : count_function
// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
//
// from_list : from_item [',' from_list]
// from_item : 'world' | object_type
//
// call_function : <function name> ['(' [arguments] ')']
// arguments : expression [',' arguments]
//
// object_type : <type path> | string
//
// assignments : assignment, [',' assignments]
// assignment : <variable name> '=' expression
// variable : <variable name> | <variable name> '.' variable
//
// bool_expression : expression comparitor expression [bool_operator bool_expression]
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
// value : variable | string | number | 'null'
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// string : ''' <some text> ''' | '"' <some text > '"'
// number : <some digits>
//
//////////
/datum/SDQL_parser
var/query_type
var/error = 0
var/list/query
var/list/tree
var/list/select_functions = list("count")
var/list/boolean_operators = list("and", "or", "&&", "||")
var/list/unary_operators = list("!", "-", "~")
var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
/datum/SDQL_parser/New(query_list)
query = query_list
/datum/SDQL_parser/proc/parse_error(error_message)
error = 1
usr << "\red SQDL2 Parsing Error: [error_message]"
return query.len + 1
/datum/SDQL_parser/proc/parse()
tree = list()
query(1, tree)
if(error)
return list()
else
return tree
/datum/SDQL_parser/proc/token(i)
if(i <= query.len)
return query[i]
else
return null
/datum/SDQL_parser/proc/tokens(i, num)
if(i + num <= query.len)
return query.Copy(i, i + num)
else
return null
/datum/SDQL_parser/proc/tokenl(i)
return lowertext(token(i))
/datum/SDQL_parser/proc
//query: select_query | delete_query | update_query
query(i, list/node)
query_type = tokenl(i)
switch(query_type)
if("select")
select_query(i, node)
if("delete")
delete_query(i, node)
if("update")
update_query(i, node)
if("call")
call_query(i, node)
if("explain")
node += "explain"
node["explain"] = list()
query(i + 1, node["explain"])
// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
select_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "select"
node["select"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
delete_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "delete"
node["delete"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
update_query(i, list/node)
var/list/select = list()
i = select_list(i + 1, select)
node += "update"
node["update"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) != "set")
i = parse_error("UPDATE has misplaced SET")
var/list/set_assignments = list()
i = assignments(i + 1, set_assignments)
node += "set"
node["set"] = set_assignments
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
call_query(i, list/node)
var/list/func = list()
i = call_function(i + 1, func)
node += "call"
node["call"] = func
if(tokenl(i) != "on")
return i
var/list/select = list()
i = select_list(i + 1, select)
node += "on"
node["on"] = select
var/list/from = list()
if(tokenl(i) in list("from", "in"))
i = from_list(i + 1, from)
else
from += "world"
node += "from"
node["from"] = from
if(tokenl(i) == "where")
var/list/where = list()
i = bool_expression(i + 1, where)
node += "where"
node["where"] = where
return i
//select_list: select_item [',' select_list]
select_list(i, list/node)
i = select_item(i, node)
if(token(i) == ",")
i = select_list(i + 1, node)
return i
//from_list: from_item [',' from_list]
from_list(i, list/node)
i = from_item(i, node)
if(token(i) == ",")
i = from_list(i + 1, node)
return i
//assignments: assignment, [',' assignments]
assignments(i, list/node)
i = assignment(i, node)
if(token(i) == ",")
i = assignments(i + 1, node)
return i
//select_item: '*' | select_function | object_type
select_item(i, list/node)
if(token(i) == "*")
node += "*"
i++
else if(tokenl(i) in select_functions)
i = select_function(i, node)
else
i = object_type(i, node)
return i
//from_item: 'world' | object_type
from_item(i, list/node)
if(token(i) == "world")
node += "world"
i++
else
i = object_type(i, node)
return i
//bool_expression: expression [bool_operator bool_expression]
bool_expression(i, list/node)
var/list/bool = list()
i = expression(i, bool)
node[++node.len] = bool
if(tokenl(i) in boolean_operators)
i = bool_operator(i, node)
i = bool_expression(i, node)
return i
//assignment: <variable name> '=' expression
assignment(i, list/node)
node += token(i)
if(token(i + 1) == "=")
var/varname = token(i)
node[varname] = list()
i = expression(i + 2, node[varname])
else
parse_error("Assignment expected, but no = found")
return i
//variable: <variable name> | <variable name> '.' variable
variable(i, list/node)
var/list/L = list(token(i))
node[++node.len] = L
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
else
i++
return i
//object_type: <type path> | string
object_type(i, list/node)
if(copytext(token(i), 1, 2) == "/")
node += token(i)
else
i = string(i, node)
return i + 1
//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
comparitor(i, list/node)
if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//bool_operator: 'AND' | '&&' | 'OR' | '||'
bool_operator(i, list/node)
if(tokenl(i) in list("and", "or", "&&", "||"))
node += token(i)
else
parse_error("Unknown comparitor [token(i)]")
return i + 1
//string: ''' <some text> ''' | '"' <some text > '"'
string(i, list/node)
if(copytext(token(i), 1, 2) in list("'", "\""))
node += token(i)
else
parse_error("Expected string but found '[token(i)]'")
return i + 1
//call_function: <function name> ['(' [arguments] ')']
call_function(i, list/node)
parse_error("Sorry, function calls aren't available yet")
return i
//select_function: count_function
select_function(i, list/node)
parse_error("Sorry, function calls aren't available yet")
return i
//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
expression(i, list/node)
if(token(i) in unary_operators)
i = unary_expression(i, node)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
node[++node.len] = expr
else
i = value(i, node)
if(token(i) in binary_operators)
i = binary_operator(i, node)
i = expression(i, node)
else if(token(i) in comparitors)
i = binary_operator(i, node)
var/list/rhs = list()
i = expression(i, rhs)
node[++node.len] = rhs
return i
//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
unary_expression(i, list/node)
if(token(i) in unary_operators)
var/list/unary_exp = list()
unary_exp += token(i)
i++
if(token(i) in unary_operators)
i = unary_expression(i, unary_exp)
else if(token(i) == "(")
var/list/expr = list()
i = expression(i + 1, expr)
if(token(i) != ")")
parse_error("Missing ) at end of expression.")
else
i++
unary_exp[++unary_exp.len] = expr
else
i = value(i, unary_exp)
node[++node.len] = unary_exp
else
parse_error("Expected unary operator but found '[token(i)]'")
return i
//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
binary_operator(i, list/node)
if(token(i) in (binary_operators + comparitors))
node += token(i)
else
parse_error("Unknown binary operator [token(i)]")
return i + 1
//value: variable | string | number | 'null'
value(i, list/node)
if(token(i) == "null")
node += "null"
i++
else if(isnum(text2num(token(i))))
node += text2num(token(i))
i++
else if(copytext(token(i), 1, 2) in list("'", "\""))
i = string(i, node)
else
i = variable(i, node)
return i
/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/

View File

@@ -221,6 +221,50 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
return 1
/*
Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly
Ccomp's first proc.
*/
/client/proc/allow_character_respawn()
set category = "Special Verbs"
set name = "Allow player to respawn"
set desc = "Let's the player bypass the 30 minute wait to respawn."
if(!holder)
src << "Only administrators may use this command."
var/any = 0
var/list/mobs = list()
var/list/ghosts = list()
var/list/sortmob = sortAtom(mob_list) // get the mob list.
for(var/mob/dead/observer/M in sortmob)
mobs.Add(M) //filter it where it's only ghosts
any = 1 //if no ghosts show up, any will just be 0
if(!any)
src << "There doesn't appear to be any ghosts for you to select."
return
for(var/mob/M in mobs)
var/name = M.name
ghosts[name] = M //get the name of the mob for the popup list
var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts
if(!target)
src << "Hrm, appears you didn't select a ghost" // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error.
return
var/mob/M = ghosts[target]
M.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb.
timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure
there won't be an autopsy.
*/
M:show_message(text("\blue <B>You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead.</B>"), 1)
log_admin("[key_name(usr)] allowed [key_name(M)] to bypass the 30 minute respawn limit")
message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(M)] to bypass the 30 minute respawn limit", 1)
/*
If a guy was gibbed and you want to revive him, this is a good way to do so.
Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one.

View File

@@ -66,7 +66,7 @@ var/global/vox_tick = 1
C.registered_user = src
var/obj/item/weapon/storage/wallet/W = new(src)
W.handle_item_insertion(C)
spawn_money(rand(100,300)*5,W)
spawn_money(rand(50,150)*10,W)
equip_to_slot_or_del(W, slot_wear_id)
var/obj/item/weapon/implant/cortical/I = new(src)