elseif flag == p.flags.mdy then
self.mdyDate = true
return true
elseif flag == p.flags.single then
self.singleClaim = true
return true
elseif flag == p.flags.sourced then
self.sourcedOnly = true
return true
elseif flag == p.flags.edit then
self.editable = true
return true
elseif flag == p.flags.editAtEnd then
self.editable = true
self.editAtEnd = true
return true
elseif flag == p.flags.best or flag:match('^'..p.flags.preferred..'[+-]?$') or flag:match('^'..p.flags.normal..'[+-]?$') or flag:match('^'..p.flags.deprecated..'[+-]?$') then
self:setRank(flag)
return true
elseif flag == p.flags.future or flag == p.flags.current or flag == p.flags.former then
self:setPeriod(flag)
return true
elseif flag == "" then
-- ignore empty flags and carry on
return true
else
return false
end
end  
function Config:processFlagOrCommand(flag)
local param = ""  
if not flag then
return false
end  
if flag == p.claimCommands.property or flag == p.claimCommands.properties then
param = parameters.property
elseif flag == p.claimCommands.qualifier or flag == p.claimCommands.qualifiers then
self.states.qualifiersCount = self.states.qualifiersCount + 1
param = parameters.qualifier .. self.states.qualifiersCount
self.separators["sep"..param] = {copyTable(defaultSeparators["sep%q\\d"])}
elseif flag == p.claimCommands.reference or flag == p.claimCommands.references then
param = parameters.reference
else
return self:processFlag(flag)
end  
if self.states[param] then
return false
end  
-- create a new state for each command
self.states[param] = State:new(self, param)  
-- use "%x" as the general parameter name
self.states[param].parsedFormat = parseFormat(parameters.general) -- will be overwritten for param=="%p"  
-- set the separator
self.states[param].separator = self.separators["sep"..param] -- will be nil for param=="%p", which will be set separately  
if flag == p.claimCommands.property or flag == p.claimCommands.qualifier or flag == p.claimCommands.reference then
self.states[param].singleValue = true
end  
self.curState = self.states[param]  
return true
end  
function Config:processSeparators(args)
local sep  
for i, v in pairs(self.separators) do
if args[i] then
sep = replaceSpecialChars(args[i])  
if sep ~= "" then
self.separators[i][1] = {sep}
else
self.separators[i][1] = nil
end
end
end
end  
function Config:setFormatAndSeparators(state, parsedFormat)
state.parsedFormat = parsedFormat
state.separator = self.separators["sep"]
state.movSeparator = self.separators["sep"..parameters.separator]
state.puncMark = self.separators["punc"]
end  
-- determines if a claim has references by prefetching them from the claim using getReferences,
-- which applies some filtering that determines if a reference is actually returned,
-- and caches the references for later use
function State:isSourced(claim)
self.conf.prefetchedRefs = self:getReferences(claim)
return (#self.conf.prefetchedRefs > 0)
end  
function State:resetCaches
-- any prefetched references of the previous claim must not be used
self.conf.prefetchedRefs = nil
end  
function State:claimMatches(claim)
local matches, rankPos  
-- first of all, reset any cached values used for the previous claim
self:resetCaches  
-- if a property value was given, check if it matches the claim's property value
if self.conf.propertyValue then
matches = self.conf:snakEqualsValue(claim.mainsnak, self.conf.propertyValue)
else
matches = true
end  
-- if any qualifier values were given, check if each matches one of the claim's qualifier values
for i, v in pairs(self.conf.qualifierIDsAndValues) do
matches = (matches and self.conf:qualifierMatches(claim, i, v))
end  
-- check if the claim's rank and time period match
rankPos = rankTable[claim.rank] or 4
matches = (matches and self.conf:rankMatches(rankPos) and self.conf:timeMatches(claim))  
-- if only claims with references must be returned, check if this one has any
if self.conf.sourcedOnly then
matches = (matches and self:isSourced(claim)) -- prefetches and caches references
end  
return matches, rankPos
end  
function State:out
local result -- collection of arrays with value objects
local valuesArray -- array with value objects
local sep = nil -- value object
local out = {} -- array with value objects  
local function walk(formatTable, result)
local valuesArray = {} -- array with value objects  
for i, v in pairs(formatTable.req) do
if not result[i] or not result[i][1] then
-- we've got no result for a parameter that is required on this level,
-- so skip this level (and its children) by returning an empty result
return {}
end
end  
for _, v in ipairs(formatTable) do
if v.param then
valuesArray = mergeArrays(valuesArray, result[v.str])
elseif v.str ~= "" then
valuesArray[#valuesArray + 1] = {v.str}
end  
if v.child then
valuesArray = mergeArrays(valuesArray, walk(v.child, result))
end
end  
return valuesArray
end  
-- iterate through the results from back to front, so that we know when to add separators
for i = #self.results, 1, -1 do
result = self.results[i]  
-- if there is already some output, then add the separators
if #out > 0 then
sep = self.separator[1] -- fixed separator
result[parameters.separator] = {self.movSeparator[1]} -- movable separator
else
sep = nil
result[parameters.separator] = {self.puncMark[1]} -- optional punctuation mark
end  
valuesArray = walk(self.parsedFormat, result)  
if #valuesArray > 0 then
if sep then
valuesArray[#valuesArray + 1] = sep
end  
out = mergeArrays(valuesArray, out)
end
end  
-- reset state before next iteration
self.results = {}  
return out
end  
-- level 1 hook
function State:getProperty(claim)
local value = {self:getValue(claim.mainsnak)} -- create one value object  
if #value > 0 then
return {value} -- wrap the value object in an array and return it
else
return {} -- return empty array if there was no value
end
end  
-- level 1 hook
function State:getQualifiers(claim, param)
local qualifiers  
if claim.qualifiers then qualifiers = claim.qualifiers[self.conf.qualifierIDs[param]] end
if qualifiers then
-- iterate through claim's qualifier statements to collect their values;
-- return array with multiple value objects
return self.conf.states[param]:iterate(qualifiers, {[parameters.general] = hookNames[parameters.qualifier.."\\d"][2], count = 1}) -- pass qualifier state with level 2 hook
else
return {} -- return empty array
end
end  
-- level 2 hook
function State:getQualifier(snak)
local value = {self:getValue(snak)} -- create one value object  
if #value > 0 then
return {value} -- wrap the value object in an array and return it
else
return {} -- return empty array if there was no value
end
end  
-- level 1 hook
function State:getAllQualifiers(claim, param, result, hooks)
local out = {} -- array with value objects
local sep = self.conf.separators["sep"..parameters.qualifier][1] -- value object  
-- iterate through the output of the separate "qualifier(s)" commands
for i = 1, self.conf.states.qualifiersCount do  
-- if a hook has not been called yet, call it now
if not result[parameters.qualifier..i] then
self:callHook(parameters.qualifier..i, hooks, claim, result)
end  
-- if there is output for this particular "qualifier(s)" command, then add it
if result[parameters.qualifier..i] and result[parameters.qualifier..i][1] then  
-- if there is already some output, then add the separator
if #out > 0 and sep then
out[#out + 1] = sep
end  
out = mergeArrays(out, result[parameters.qualifier..i])
end
end  
return out
end  
-- level 1 hook
function State:getReferences(claim)
if self.conf.prefetchedRefs then
-- return references that have been prefetched by isSourced
return self.conf.prefetchedRefs
end  
if claim.references then
-- iterate through claim's reference statements to collect their values;
-- return array with multiple value objects
return self.conf.states[parameters.reference]:iterate(claim.references, {[parameters.general] = hookNames[parameters.reference][2], count = 1}) -- pass reference state with level 2 hook
else