From cd06bf07e09352f437a64e3a88d05048f824128f Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 23 Mar 2016 05:59:17 -0400 Subject: [PATCH] Ports more sdql features from vg --- code/modules/admin/verbs/SDQL2/SDQL_2.dm | 168 ++++++++++-------- .../admin/verbs/SDQL2/SDQL_2_parser.dm | 45 ++++- 2 files changed, 131 insertions(+), 82 deletions(-) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index b4015ed5b8d..e58e59209f6 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -42,105 +42,113 @@ query_log = "[key_name(usr)] [query_log]" log_admin(query_log) - for(var/list/query_tree in querys) - var/list/from_objs = list() - var/list/select_types = list() + try + for(var/list/query_tree in querys) + 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 + switch(query_tree[1]) + if("explain") + SDQL_testout(query_tree["explain"]) return - if("select", "delete", "update") - select_types = query_tree[query_tree[1]] + if("call") + if("on" in query_tree) + select_types = query_tree["on"] + else + return - from_objs = SDQL_from_objs(query_tree["from"]) + if("select", "delete", "update") + select_types = query_tree[query_tree[1]] - var/list/objs = list() + from_objs = SDQL_from_objs(query_tree["from"]) - for(var/type in select_types) - var/char = copytext(type, 1, 2) + var/list/objs = list() - if(char == "/" || char == "*") - for(var/from in from_objs) - objs += SDQL_get_all(type, from) + for(var/type in select_types) + var/char = copytext(type, 1, 2) - else if(char == "'" || char == "\"") - objs += locate(copytext(type, 2, length(type))) + if(char == "/" || char == "*") + for(var/from in from_objs) + objs += SDQL_get_all(type, from) - 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 + else if(char == "'" || char == "\"") + objs += locate(copytext(type, 2, length(type))) - switch(query_tree[1]) - if("call") - var/list/call_list = query_tree["call"] - var/list/args_list = query_tree["args"] + 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 - for(var/datum/d in objs) - for(var/v in call_list) - // To stop any procs which sleep from executing slowly. - if(d) - if(hascall(d, v)) - var/list/arguments[0] - for(var/list/arg in args_list) - arguments += SDQL_expression(d, arg) - spawn() call(d, v)(arglist(arguments)) // Spawn in case the function sleeps. + switch(query_tree[1]) + if("call") + var/list/call_list = query_tree["call"] + var/list/args_list = query_tree["args"] - if("delete") - for(var/datum/d in objs) - del(d) + for(var/datum/d in objs) + for(var/v in call_list) + var/list/arguments[0] + for(var/list/arg in args_list) + arguments += SDQL_expression(d, arg) - if("select") - var/text = "" - for(var/datum/t in objs) - text += "\ref[t]" - if(istype(t, /atom)) - var/atom/a = t + if(copytext(v, 1, 8) == "global.") // Global proc. + spawn() + call("/proc/[copytext(v, 8)]")(arglist(arguments)) + else if(d) + if(hascall(d, v)) + spawn() + call(d, v)(arglist(arguments)) // Spawn in case the function sleeps. - if(a.x) - text += ": [t] at ([a.x], [a.y], [a.z])
" + if("delete") + for(var/datum/d in objs) + del(d) - else if(a.loc && a.loc.x) - text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
" + if("select") + var/text = "" + for(var/datum/t in objs) + text += "\ref[t]" + if(istype(t, /atom)) + var/atom/a = t + + if(a.x) + text += ": [t] at ([a.x], [a.y], [a.z])
" + + else if(a.loc && a.loc.x) + text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
" + + else + text += ": [t]
" else text += ": [t]
" - else - text += ": [t]
" + usr << browse(text, "window=SDQL-result") - 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("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 - if(istype(d, /turf)) - for(var/v in vals) - if(v == "x" || v == "y" || v == "z") - continue + d.vars[v] = vals[v] - d.vars[v] = vals[v] - - else - for(var/v in vals) - d.vars[v] = vals[v] + else + for(var/v in vals) + d.vars[v] = vals[v] + catch(var/exception/e) + usr << "A runtime error has occured during the execution of your query and your query has been aborted." + usr << "[e]" /proc/SDQL_parse(list/query_list) var/datum/SDQL_parser/parser = new() @@ -353,6 +361,12 @@ else if(copytext(expression[i], 1, 2) in list("'", "\"")) val = copytext(expression[i], 2, length(expression[i])) + else if(expression[i] == "{") + var/list/expressions_list = expression[++i] + val = list() + for(var/list/expression_list in expressions_list) + val += SDQL_expression(object, expression_list) + else val = SDQL_var(object, expression, i) i = expression.len @@ -392,7 +406,7 @@ /proc/SDQL2_tokenize(query_text) var/list/whitespace = list(" ", "\n", "\t") - var/list/single = list("(", ")", ",", "+", "-", ".", ";", "\[", "\]") + var/list/single = list("(", ")", ",", "+", "-", ".", ";", "\[", "\]", "{", "}") var/list/multi = list( "=" = list("", "="), "<" = list("", "=", ">"), diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm index e5d983b7649..f2ec46111ba 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm @@ -31,12 +31,13 @@ // expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression] // unary_expression : unary_operator ( unary_expression | value | '(' expression ')' ) // comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>=' -// value : variable | string | number | 'null' +// value : variable | string | array | number | 'null' // unary_operator : '!' | '-' | '~' // binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^' // bool_operator : 'AND' | '&&' | 'OR' | '||' // // string : ''' ''' | '"' '"' +// array : '{' [arguments] '}' // number : // ////////// @@ -336,7 +337,7 @@ variable(i, list/node) var/list/L = list(token(i)) node[++node.len] = L - + if(token(i) == "\[") L += token(i + 1) i += 2 @@ -401,12 +402,43 @@ return i + 1 + //array: '{' expression, expression, ... '}' + array(var/i, var/list/node) + // Arrays get turned into this: list("{", list(exp_1a = exp_1b, ...), ...), "{" is to mark the next node as an array. + if(copytext(token(i), 1, 2) != "{") + parse_error("Expected an array but found '[token(i)]'") + return i + 1 + + node += token(i) // Add the "{" + var/list/expression_list = list() + + if(token(i + 1) != "}") + var/list/temp_expression_list = list() + + do + i = expression(i + 1, temp_expression_list) + + if(token(i) == ",") + expression_list[++expression_list.len] = temp_expression_list + temp_expression_list = list() + while(token(i) && token(i) != "}") + + expression_list[++expression_list.len] = temp_expression_list + else + i++ + + node[++node.len] = expression_list + return i + 1 //call_function: ['(' [arguments] ')'] call_function(i, list/node, list/arguments) var/list/cur_argument = list() if(length(tokenl(i))) - node += token(i++) + var/procname = "" + if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc. + i += 2 + procname = "global." + node += procname + token(i++) if(token(i) != "(") parse_error("Expected ( but found '[token(i)]'") else if(token(i + 1) != ")") @@ -526,11 +558,11 @@ if(token(i) == "null") node += "null" i++ - + else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3)))) node += hex2num(copytext(token(i), 3)) i++ - + else if(isnum(text2num(token(i)))) node += text2num(token(i)) i++ @@ -538,6 +570,9 @@ else if(copytext(token(i), 1, 2) in list("'", "\"")) i = string(i, node) + else if(copytext(token(i), 1, 2) == "{") // Start a list. + i = array(i, node) + else i = variable(i, node)