From e5d85a20ee44dfc5819da20fd314f786badce6ff Mon Sep 17 00:00:00 2001 From: "Johnny C. Lam" Date: Sun, 13 Jul 2014 11:32:25 +0000 Subject: [PATCH] Allow for multiple checkbox and list/item pairs in parameters. List/item pairs should now use the following syntax: list=name item=value --> listitem=name:value Isolate code to handle deprecated parameters (checkboxon, checkboxoff, list, item, mastery) into OvaleAST:FlattenParameters() so that other modules no longer need logic to handle the deprecated features when using parameters. git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@1551 d5049fe3-3747-40f7-a4b5-f36d6801af5f --- OvaleAST.lua | 178 +++++++++++++++++++++++++++++++++++++++++++++--------- OvaleCompile.lua | 81 ++++++++----------------- 2 files changed, 173 insertions(+), 86 deletions(-) diff --git a/OvaleAST.lua b/OvaleAST.lua index 65b4a43..10e341d 100644 --- a/OvaleAST.lua +++ b/OvaleAST.lua @@ -99,15 +99,16 @@ local DECLARATION_KEYWORD = { local PARAMETER_KEYWORD = { ["checkbox"] = true, - ["checkboxoff"] = true, - ["checkboxon"] = true, + ["checkboxoff"] = true, -- deprecated + ["checkboxon"] = true, -- deprecated ["glyph"] = true, ["if_spell"] = true, ["if_stance"] = true, - ["item"] = true, + ["item"] = true, -- deprecated ["itemcount"] = true, ["itemset"] = true, - ["list"] = true, + ["list"] = true, -- deprecated + ["listitem"] = true, ["specialization"] = true, ["stance"] = true, ["talent"] = true, @@ -203,6 +204,7 @@ end local self_indent = 0 local self_outputPool = OvalePool("OvaleAST_outputPool") +local self_controlPool = OvalePool("OvaleAST_controlPool") local self_parametersPool = OvalePool("OvaleAST_parametersPool") local self_childrenPool = OvalePool("OvaleAST_childrenPool") local self_pool = OvalePool("OvaleAST_pool") @@ -349,6 +351,30 @@ local function GetTokenIterator(s) return OvaleLexer.scan(s, MATCHES, exclude) end +-- "Flatten" a parameter value node into a string. +local function FlattenParameterValue(parameterValue) + local value = parameterValue + if type(parameterValue) == "table" then + local node = parameterValue + local isBang = false + if node.type == "bang_value" then + isBang = true + node = node.child[1] + end + if node.type == "value" then + value = node.value + elseif node.type == "variable" then + value = node.name + elseif node.type == "string" then + value = node.value + end + if isBang then + value = "!" .. tostring(value) + end + end + return value +end + --[[------------------------ "Unparser" functions --]]------------------------ @@ -530,6 +556,14 @@ UnparseParameters = function(parameters) for k, v in pairs(parameters) do if type(k) == "number" and k <= N then -- Already output in previous loop. + elseif k == "checkbox" then + for _, name in ipairs(v) do + output[#output + 1] = format("checkbox=%s", Unparse(name)) + end + elseif k == "listitem" then + for list, item in pairs(v) do + output[#output + 1] = format("listitem=%s:%s", list, Unparse(item)) + end elseif type(v) == "table" then output[#output + 1] = format("%s=%s", k, Unparse(v)) elseif k == "filter" or k == "target" then @@ -1524,14 +1558,50 @@ ParseParameters = function(tokenStream, nodeList, annotation, isList) if tokenType == "=" then -- Consume the '=' token. tokenStream:Consume() - -- Get the value. - ok, node = ParseParameterValue(tokenStream, nodeList, annotation) - if ok then + if name == "checkbox" or name == "listitem" then + local control = parameters[name] or self_controlPool:Get() + if name == "checkbox" then + -- Get the checkbox name. + ok, node = ParseParameterValue(tokenStream, nodeList, annotation) + if ok then + control[#control + 1] = node + end + else -- if name == "listitem" then + -- Consume the list name. + tokenType, token = tokenStream:Consume() + local list + if tokenType == "name" then + list = token + else + SyntaxError(tokenStream, "Syntax error: unexpected token '%s' when parsing PARAMETERS; name expected.", token) + ok = false + end + if ok then + -- Consume the ':' token. + tokenType, token = tokenStream:Consume() + if tokenType ~= ":" then + SyntaxError(tokenStream, "Syntax error: unexpected token '%s' when parsing PARAMETERS; ':' expected.", token) + ok = false + end + end + if ok then + -- Consume the list item. + ok, node = ParseParameterValue(tokenStream, nodeList, annotation) + end + if ok then + control[list] = node + end + end + if not parameters[name] then + parameters[name] = control + annotation.controlList = annotation.controlList or {} + annotation.controlList[#annotation.controlList + 1] = control + end + else + -- Get the value. + ok, node = ParseParameterValue(tokenStream, nodeList, annotation) parameters[name] = node end - elseif PARAMETER_KEYWORD[name] then - SyntaxError(tokenStream, "Syntax error: unexpected keyword '%s' when parsing PARAMETERS; simple expression expected.", name) - ok = false else parameters[#parameters + 1] = node end @@ -2021,6 +2091,7 @@ end function OvaleAST:Debug() self_pool:Debug() self_parametersPool:Debug() + self_controlPool:Debug() self_childrenPool:Debug() self_outputPool:Debug() end @@ -2045,6 +2116,11 @@ function OvaleAST:NodeToString(node) end function OvaleAST:ReleaseAnnotation(annotation) + if annotation.controlList then + for _, control in ipairs(annotation.controlList) do + self_controlPool:Release(control) + end + end if annotation.parametersList then for _, parameters in ipairs(annotation.parametersList) do self_parametersPool:Release(parameters) @@ -2209,29 +2285,65 @@ function OvaleAST:FlattenParameters(ast) local parameters = self_parametersPool:Get() for key, value in pairs(node.rawParams) do -- Lookup the key. - if type(key) ~= "number" and dictionary and dictionary[key] then - key = dictionary[key] - end - -- Evaluate the value. - if type(value) == "table" then - local node = value - local isBang = false - if node.type == "bang_value" then - isBang = true - node = node.child[1] + if key == "checkbox" or key == "listitem" then + local control = parameters[key] or self_controlPool:Get() + if key == "checkbox" then + for i, name in ipairs(value) do + control[i] = FlattenParameterValue(name) + end + else -- if key == "listitem" then + for list, item in pairs(value) do + control[list] = FlattenParameterValue(item) + end + end + if not parameters[key] then + parameters[key] = control + annotation.controlList = annotation.controlList or {} + annotation.controlList[#annotation.controlList + 1] = control end - if node.type == "value" then - value = node.value - elseif node.type == "variable" then - value = node.name - elseif node.type == "string" then - value = node.value + elseif key == "checkboxon" or key == "checkboxoff" then + -- Deprecated: checkboxon + -- Deprecated: checkboxoff + local control = parameters.checkbox or self_controlPool:Get() + local name = FlattenParameterValue(value) + if key == "checkboxon" then + Ovale:OneTimeMessage("Warning: 'checkboxon=%s' is deprecated; use 'checkbox=%s' instead.", name, name) + control[#control + 1] = name + elseif key == "checkboxoff" then + Ovale:OneTimeMessage("Warning: 'checkboxoff=%s' is deprecated; use 'checkbox=!%s' instead.", name, name) + control[#control + 1] = "!" .. name end - if isBang then - value = "!" .. tostring(value) + if not parameters.checkbox then + parameters.checkbox = control + annotation.controlList = annotation.controlList or {} + annotation.controlList[#annotation.controlList + 1] = control end + elseif key == "list" or key == "item" then + -- Deprecated: list + -- Deprecated: item + if key == "list" and node.rawParams.item then + local control = parameters.listitem or self_controlPool:Get() + local list = FlattenParameterValue(value) + local item = FlattenParameterValue(node.rawParams.item) + Ovale:OneTimeMessage("Warning: 'list=%s item=%s' is deprecated; use 'listitem=%s:%s' instead.", list, item, list, item) + control[list] = item + if not parameters.listitem then + parameters.listitem = control + annotation.controlList = annotation.controlList or {} + annotation.controlList[#annotation.controlList + 1] = control + end + end + elseif key == "mastery" then + -- Deprecated: mastery -> specialization + local spec = FlattenParameterValue(value) + Ovale:OneTimeMessage("Warning: 'mastery=%s' is deprecated; use 'specialization=%s' instead.", spec, spec) + parameters.specialization = spec + else + if type(key) ~= "number" and dictionary and dictionary[key] then + key = dictionary[key] + end + parameters[key] = FlattenParameterValue(value) end - parameters[key] = value end node.params = parameters annotation.parametersList = annotation.parametersList or {} @@ -2246,6 +2358,14 @@ function OvaleAST:FlattenParameters(ast) for k, v in pairs(parameters) do if type(k) == "number" and k <= N then -- Already output in previous loop. + elseif k == "checkbox" then + for _, name in ipairs(v) do + output[#output + 1] = format("checkbox=%s", name) + end + elseif k == "listitem" then + for list, item in ipairs(v) do + output[#output + 1] = format("listitem=%s:%s", list, item) + end else output[#output + 1] = format("%s=%s", k, v) end diff --git a/OvaleCompile.lua b/OvaleCompile.lua index 770a144..77a3625 100644 --- a/OvaleCompile.lua +++ b/OvaleCompile.lua @@ -106,13 +106,6 @@ local function TestConditions(parameters) local isSpec = OvalePaperDoll:IsSpecialization(spec) boolean = (required and isSpec) or (not required and not isSpec) end - -- Deprecated: mastery -> specialization - if boolean and parameters.mastery then - Ovale:OneTimeMessage("Warning: 'mastery' is deprecated; use 'specialization' instead.") - local spec, required = RequireValue(parameters.mastery) - local isSpec = OvalePaperDoll:IsSpecialization(spec) - boolean = (required and isSpec) or (not required and not isSpec) - end if boolean and parameters.if_stance then self_compileOnStances = true local stance, required = RequireValue(parameters.if_stance) @@ -137,50 +130,28 @@ local function TestConditions(parameters) do local profile if boolean and parameters.checkbox then - local name, required = RequireValue(parameters.checkbox) - local checkBox = Ovale.casesACocher[name] or {} - checkBox.compile = true - Ovale.casesACocher[name] = checkBox - -- Check the value of the checkbox. - profile = profile or OvaleOptions:GetProfile() - local isChecked = (profile.check[name] ~= nil) - boolean = (required and isChecked) or (not required and not isChecked) - end - -- Deprecated: checkboxon - if boolean and parameters.checkboxon then - Ovale:OneTimeMessage("Warning: 'checkboxon=name' is deprecated; use 'checkbox=name' instead.") - -- Flag this checkbox as triggering a script evaluation. - local name = parameters.checkboxon - local checkBox = Ovale.casesACocher[name] or {} - checkBox.compile = true - Ovale.casesACocher[name] = checkBox - -- Check the value of the checkbox. - profile = profile or OvaleOptions:GetProfile() - boolean = (profile.check[name] ~= nil) - end - -- Deprecated: checkboxoff - if boolean and parameters.checkboxoff then - Ovale:OneTimeMessage("Warning: 'checkboxoff=name' is deprecated; use 'checkbox=!name' instead.") - -- Flag this checkbox as triggering a script evaluation. - local name = parameters.checkboxon - local checkBox = Ovale.casesACocher[name] or {} - checkBox.compile = true - Ovale.casesACocher[name] = checkBox - -- Check the value of the checkbox. - profile = profile or OvaleOptions:GetProfile() - boolean = (profile.check[name] == nil) + for _, checkbox in ipairs(parameters.checkbox) do + local name, required = RequireValue(checkbox) + local control = Ovale.casesACocher[name] or {} + control.compile = true + Ovale.casesACocher[name] = control + -- Check the value of the checkbox. + profile = profile or OvaleOptions:GetProfile() + local isChecked = (profile.check[name] ~= nil) + boolean = (required and isChecked) or (not required and not isChecked) + end end - if boolean and parameters.list and parameters.item then - -- Flag this list as triggering a script evaluation. - local name = parameters.list - local item, required = RequireValue(parameters.item) - local list = Ovale.listes[name] or { items = {}, default = nil } - list.compile = true - Ovale.listes[name] = list - -- Check the selected item in the list. - profile = profile or OvaleOptions:GetProfile() - local isSelected = (profile.list[name] == item) - boolean = (required and isSelected) or (not required and not isSelected) + if boolean and parameters.listitem then + for list, listitem in pairs(parameters.listitem) do + local item, required = RequireValue(listitem) + local control = Ovale.listes[list] or { items = {}, default = nil } + control.compile = true + Ovale.listes[list] = control + -- Check the selected item in the list. + profile = profile or OvaleOptions:GetProfile() + local isSelected = (profile.list[list] == item) + boolean = (required and isSelected) or (not required and not isSelected) + end end end profiler.Stop("OvaleCompile_TestConditions") @@ -323,8 +294,7 @@ local function EvaluateSpellAuraList(node) local tbl = auraTable[filter] or {} local count = 0 for k, v in pairs(parameters) do - -- Deprecated: "mastery" can't be a keyword since it's the same as the name of the raid buff. - if not OvaleAST.PARAMETER_KEYWORD[k] and k ~= "mastery" then + if not OvaleAST.PARAMETER_KEYWORD[k] then tbl[k] = v count = count + 1 end @@ -365,11 +335,8 @@ local function EvaluateSpellInfo(node) OvaleData.buffSpellList[v] = list elseif k == "sharedcd" then OvaleCooldown:AddSharedCooldown(v, spellId) - else - -- Deprecated: "mastery" can't be a keyword since it's the same as the name of the raid buff. - if not OvaleAST.PARAMETER_KEYWORD[k] and k ~= "mastery" then - si[k] = v - end + elseif not OvaleAST.PARAMETER_KEYWORD[k] then + si[k] = v end end end -- 1.7.9.5