diff --git a/manual.md b/manual.md index f459a85..0533bea 100644 --- a/manual.md +++ b/manual.md @@ -376,7 +376,7 @@ Parameter: - "start_condition" is a string that has the name of the nonterminal where is the start condition, or nil that means "main". Return: -- false if the phrase syntax fail to add into the instance due to some errors. +- ID for the syntax added into the phrase, or nil if the phrase syntax fail to add into the phrase generator due to some errors. Errors: - Invalid parameter error if the parameter is neither a string or a compiled data. @@ -386,6 +386,19 @@ Errors: Note: - output_error() and output_compile_error() is called if some errors are detected. +### delete(self, id) + +It deletes a phrase syntax from the instance. + +Parameter: +- "id" is the ID for the phrase syntax to delete from the instance. + +Return: +- true if the syntax is deleted. + +Note: +- This is an O(n) function, because it's assumed that the function is not used frequently. + ### generate(self, ext_context) It generates a phrase text. diff --git a/scripts/phrase.lua b/scripts/phrase.lua index 81278e2..2337397 100644 --- a/scripts/phrase.lua +++ b/scripts/phrase.lua @@ -59,7 +59,7 @@ end param: text_or_compiled A text or a compiled data of the phrase syntax. start_condition A string that has the name of the nonterminal where is the start condition, or nil that means "main". - return: false if the phrase syntax fail to add into the phrase generator due to some errors. + return: ID for the syntax added into the phrase, or nil if the phrase syntax fail to add into the phrase generator due to some errors. note: output_error() and output_compile_error() is if when some errors are detected. --]] @@ -74,7 +74,7 @@ function phrase:add(text_or_compiled, start_condition) syntax = text_or_compiled.data:clone() else phrase.output_error("Invalid parameter type.\n") - return false + return nil end if err_msg == "" then if start_condition == nil then @@ -87,12 +87,25 @@ function phrase:add(text_or_compiled, start_condition) end if err_msg ~= "" then self.output_compile_error(text, err_msg) - return false + return nil else - return true + return syntax end end +--[[ + Delete the phrase syntax from the instance. + + param: ID for the syntax. + + return: true if the syntax is deleted. + + note: This is an O(n) function, because it's assumed that the function is not used frequently. +--]] +function phrase:delete(id) + return self.data:delete(id) +end + --[[ Generate a phrase. diff --git a/scripts/phrase/data.lua b/scripts/phrase/data.lua index c042120..e5504aa 100644 --- a/scripts/phrase/data.lua +++ b/scripts/phrase/data.lua @@ -661,6 +661,7 @@ end .generate(): generate a text. .add(): add a syntax into the phrase. + .delete(): delete a syntax into the phrase. .equalize_chance(): Equalize the chance to select each phrase syntax. .get_number_of_syntax(): The number of the syntaxes in the phrase. .get_weight(): The sum of the weight of the syntaxes. @@ -710,6 +711,29 @@ function data.new_phrase_data () return true end + phrase.delete = function (self, id) + local deleted = false + local sum = 0.0 + for i, v in ipairs(self.syntaxes) do + if deleted then + self.syntaxes[i - 1] = self.syntaxes[i] + sum = sum + self.syntaxes[i - 1]:get_weight() + self.weights[i - 1] = sum + elseif v == id then + deleted = true + if i >= 2 then + sum = self.weights[i - 1] + end + end + end + if deleted then + local last = #self.syntaxes + self.syntaxes[last] = nil + self.weights[last] = nil + end + return deleted + end + phrase.equalize_chance = function (self, enable) if enable == nil then self.equalized_chance = true diff --git a/test/test_functions.lua b/test/test_functions.lua index bad6c44..106440b 100644 --- a/test/test_functions.lua +++ b/test/test_functions.lua @@ -239,6 +239,108 @@ function test_functions.run_test() ph:generate() == "2" end + function tests.phrase_delete_first() + ut:set_random_sequence({ 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 }) + local ph = phrase.new() + local id1 = ph:add([[main = "1" 2 | 2 | 3]]) + local id2 = ph:add([[main = A | "B" 3 | C]]) + local id3 = ph:add([[main = あ | い | "う" 4]]) + local r3 = ph:generate() + local n3 = ph:get_number_of_syntax() + local c3 = ph:get_combination_number() + local w3 = ph:get_weight() + local del3 = ph:delete(id1) + local r2 = ph:generate() + local n2 = ph:get_number_of_syntax() + local c2 = ph:get_combination_number() + local w2 = ph:get_weight() + local del2 = ph:delete(id2) + local r1 = ph:generate() + local n1 = ph:get_number_of_syntax() + local c1 = ph:get_combination_number() + local w1 = ph:get_weight() + local del1 = ph:delete(id3) + local r0 = ph:generate() + local n0 = ph:get_number_of_syntax() + local c0 = ph:get_combination_number() + local w0 = ph:get_weight() + return + del1 and del2 and del3 and + id1 and id2 and id3 and + r3 == "う" and r2 == "う" and r1 == "う" and r0 == "nil" and + n3 == 3 and n2 == 2 and n1 == 1 and n0 == 0 and + c3 == 9 and c2 == 6 and c1 == 3 and c0 == 0 and + w3 == 15 and w2 == 11 and w1 == 6 and w0 == 0 + end + + function tests.phrase_delete_last() + ut:set_random_sequence({ 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 }) + local ph = phrase.new() + local id1 = ph:add([[main = "1" 2 | 2 | 3]]) + local id2 = ph:add([[main = A | "B" 3 | C]]) + local id3 = ph:add([[main = あ | い | "う" 4]]) + local r3 = ph:generate() + local n3 = ph:get_number_of_syntax() + local c3 = ph:get_combination_number() + local w3 = ph:get_weight() + local del3 = ph:delete(id3) + local r2 = ph:generate() + local n2 = ph:get_number_of_syntax() + local c2 = ph:get_combination_number() + local w2 = ph:get_weight() + local del2 = ph:delete(id2) + local r1 = ph:generate() + local n1 = ph:get_number_of_syntax() + local c1 = ph:get_combination_number() + local w1 = ph:get_weight() + local del1 = ph:delete(id1) + local r0 = ph:generate() + local n0 = ph:get_number_of_syntax() + local c0 = ph:get_combination_number() + local w0 = ph:get_weight() + return + del1 and del2 and del3 and + id1 and id2 and id3 and + r3 == "う" and r2 == "C" and r1 == "3" and r0 == "nil" and + n3 == 3 and n2 == 2 and n1 == 1 and n0 == 0 and + c3 == 9 and c2 == 6 and c1 == 3 and c0 == 0 and + w3 == 15 and w2 == 9 and w1 == 4 and w0 == 0 + end + + function tests.phrase_delete_middle() + ut:set_random_sequence({ 0.9, 0.9, 0.9, 0.9, 0.9, 0.9 }) + local ph = phrase.new() + local id1 = ph:add([[main = "1" 2 | 2 | 3]]) + local id2 = ph:add([[main = A | "B" 3 | C]]) + local id3 = ph:add([[main = あ | い | "う" 4]]) + local r3 = ph:generate() + local n3 = ph:get_number_of_syntax() + local c3 = ph:get_combination_number() + local w3 = ph:get_weight() + local del3 = ph:delete(id2) + local r2 = ph:generate() + local n2 = ph:get_number_of_syntax() + local c2 = ph:get_combination_number() + local w2 = ph:get_weight() + local del2 = ph:delete(id1) + local r1 = ph:generate() + local n1 = ph:get_number_of_syntax() + local c1 = ph:get_combination_number() + local w1 = ph:get_weight() + local del1 = ph:delete(id3) + local r0 = ph:generate() + local n0 = ph:get_number_of_syntax() + local c0 = ph:get_combination_number() + local w0 = ph:get_weight() + return + del1 and del2 and del3 and + id1 and id2 and id3 and + r3 == "う" and r2 == "う" and r1 == "う" and r0 == "nil" and + n3 == 3 and n2 == 2 and n1 == 1 and n0 == 0 and + c3 == 9 and c2 == 6 and c1 == 3 and c0 == 0 and + w3 == 15 and w2 == 10 and w1 == 6 and w0 == 0 + end + function tests.compile_add_1() local compiled = phrase.compile() local result = compiled:add([[B = 2]])