Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Real set variable #240

Closed
wants to merge 8 commits into from
6 changes: 4 additions & 2 deletions Test/TestParser/TestVariables/TestVariables.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func test_variables():

await wait_execute_script_finished(file_base_name)

assert_variable("a", TYPE_INT, 1)
assert_variable("a", TYPE_INT, 2)

assert_variable("b", TYPE_FLOAT, 2.5)

Expand All @@ -25,4 +25,6 @@ func test_variables():

assert_variable("e", TYPE_INT, Rakugo.get_variable("Sy.life"))

assert_eq(Rakugo.get_variable("f"), null)
assert_variable("e", TYPE_INT, 4)

assert_eq(Rakugo.get_variable("g"), null)
11 changes: 8 additions & 3 deletions Test/TestParser/TestVariables/TestVariables.rk
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
a = 1
b = 2.5
a = 1 + 1
b = 5/2
c = "Hello, world !"
d = a
character Sy "Sylvie"
Sy.life = 5
e = Sy.life
e = Sy.life
f = 2
f += 2
f *= 2
f /= 2

74 changes: 51 additions & 23 deletions addons/Rakugo/lib/systems/Executer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ var regex := {
}

var regex_cache := {}

var menu_jump_index:int
var menu_jump_index: int

func _init():
for key in regex:
Expand Down Expand Up @@ -88,7 +87,6 @@ func do_execute_script_end(parameters:Dictionary):
threads.erase(current_thread.get_id())

current_thread = null

current_semaphore = null

func do_execute_jump(jump_label:String, labels:Dictionary) -> int:
Expand Down Expand Up @@ -152,7 +150,9 @@ func do_execute_script(parameters:Dictionary):
var values = []

for var_name in line[3]:
var var_ = Rakugo.get_variable(var_name)
var var_ = null
if Rakugo.has_variable(var_name):
var_ = Rakugo.get_variable(var_name)
Comment on lines +153 to +155
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rakugo.get_variable return null if variable is not found. So you do not need to use has_variable before get_variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I made this if this way as Rakugo would crash when get_variable() returns null - we program it this way,
push_error() stops program no matter what is next.

func get_variable(var_name: String):
var vars_ = var_name.split(".")
match vars_.size():
1:
if store_manager.variables.has(var_name):
return store_manager.variables.get(var_name)
2:
return get_character_variable(vars_[0], vars_[1])
push_error("Rakugo does not knew a variable called: " + var_name)


if !var_:
parameters["error"] = "Executer::do_execute_script::JUMP, can not get variable :" + var_name
Expand All @@ -167,6 +167,7 @@ func do_execute_script(parameters:Dictionary):
parameters["error"] = "Executer::do_execute_script::JUMP, failed to execute expression : " + result.get_string("expression")
parameters["stop"] = true
break

else:
can_jump = true

Expand Down Expand Up @@ -238,37 +239,64 @@ func do_execute_script(parameters:Dictionary):
break

# remove 1 because we add 1 at the end of the loop
index -= 1
index -= 1

elif !(menu_jump_index in [0, menu_choices.size() - 1]):
parameters["error"] = "Executer::do_execute_script::MENU, menu_jump_index out of range: " + str(menu_jump_index) + " >= " + str(menu_choices.size())
parameters["stop"] = true
break

"SET_VARIABLE":
var rvar_name = result.get_string("rvar_name")
var text = result.get_string("text")
var operator = result.get_string("operator")
var final_value = null

var values = []
for var_name in line[3]:
var var_ = Rakugo.get_variable(var_name)

if !var_:
parameters["error"] = "Executer::do_execute_script::SET_VARIABLE, can not get variable :" + var_name
parameters["stop"] = true
break

values.push_back(var_)

final_value = line[2].execute(values)

var value
if line[2].has_execute_failed():
parameters["error"] = "Executer::do_execute_script::SET_VARIABLE, failed to execute expression : " + result.get_string("expression")
parameters["stop"] = true
break

if !rvar_name.is_empty():
value = Rakugo.get_variable(rvar_name)
if operator != "=":
if Rakugo.has_variable(rvar_name):
var org_value = Rakugo.get_variable(rvar_name)

match operator:
"+=":
Rakugo.set_variable(rvar_name, org_value + final_value)

"-=":
Rakugo.set_variable(rvar_name, org_value - final_value)

"*=":
Rakugo.set_variable(rvar_name, org_value * final_value)

"/=":
Rakugo.set_variable(rvar_name, org_value / final_value)

"%=":
Rakugo.set_variable(rvar_name, org_value % final_value)

if !value:
parameters["error"] = "Executer::do_execute_script::SET_VARIABLE, can not get variable :" + rvar_name
else:
parameters["error"] = "Executer::do_execute_script::SET_VARIABLE, variable not found : " + rvar_name
parameters["stop"] = true
break

elif !text.is_empty():
value = remove_double_quotes(text)
else:
value = result.get_string("number")

if value.is_valid_int():
value = int(value)
else:
value = float(value)

Rakugo.set_variable(result.get_string("lvar_name"), value)

# if operator is "=" or if the variable does not exist
Rakugo.set_variable(rvar_name, final_value)

_:
Rakugo.sg_custom_regex.emit(line[0], result)

Expand Down
87 changes: 49 additions & 38 deletions addons/Rakugo/lib/systems/Parser.gd
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var Regex := {
NUMERIC = "-?[0-9]\\.?[0-9]*",
STRING = "\".*\"",
VARIABLE = "((?<char_tag>{NAME})\\.)?(?<var_name>{NAME})",
ASSIGNMENT = "(=|\\+=|\\-=|\\*=|\\/=|\\%=)",
# MULTILINE_STRING = "\"\"\"(?<string>.*)\"\"\"",
}

Expand All @@ -65,13 +66,7 @@ var parser_regex :={
# jump label
JUMP = "^jump (?<label>{NAME})( if (?<expression>.+))?$",
# for setting Rakugo variables
SET_VARIABLE = "^(?<lvar_name>{VARIABLE}) = ((?<text>{STRING})|(?<number>{NUMERIC})|(?<rvar_name>{VARIABLE}))$",
# $ some_gd_script_code
# IN_LINE_GDSCRIPT = "^\\$.*",
# gdscript:
# GDSCRIPT_BLOCK = "^gdscript:",
# TRANSLATION = "\\[TR:(?<tr>.*?)]\\",
# CONDITION = "(if|elif) (?<condition>.*)",
SET_VARIABLE = "^(?<rvar_name>{VARIABLE})\\s*(?<operator>{ASSIGNMENT})\\s*(?<expression>.+)$",
}

var other_regex :={
Expand Down Expand Up @@ -107,7 +102,9 @@ func _init():

for key in other_regex:
add_regex(key, other_regex[key], other_cache, "Parser, _init, failed " + key)


# prints("SET_VARIABLE", regex_cache["SET_VARIABLE"]. get_pattern())

add_regex("VARIABLE", Regex["VARIABLE"], other_cache, "Parser, _init, failed VARIABLE")

func count_indent(s:String) -> int:
Expand All @@ -124,19 +121,42 @@ func count_indent(s:String) -> int:

return ret

func get_vars_in_expression(str_expression:String):
var sub_results = other_cache["VARIABLE"].search_all(str_expression)
var vars = []

# Expression does not like '.'
var vars_expression = []

for sub_result in sub_results:
var sub_result_str = sub_result.strings[0]

if !vars.has(sub_result_str):
vars.push_back(sub_result_str)

var var_name_expr = sub_result.get_string("char_tag")

if !var_name_expr.is_empty():
var_name_expr += "_" + sub_result.get_string("var_name")

str_expression = str_expression.replace(sub_result_str, var_name_expr)
else:
var_name_expr = sub_result.get_string("var_name")

if !vars_expression.has(var_name_expr):
vars_expression.push_back(var_name_expr)

return [vars_expression, vars]

func parse_script(lines:PackedStringArray) -> Dictionary:
if lines.is_empty():
push_error("Parser, parse_script : lines is empty !")
return {}

var parse_array:Array

var labels:Dictionary

var indent_count:int

var menu_choices

var current_menu_result

state = State.Normal
Expand Down Expand Up @@ -203,42 +223,33 @@ func parse_script(lines:PackedStringArray) -> Dictionary:
if str_expression.is_empty():
parse_array.push_back([key, result])
break

var vars = get_vars_in_expression(str_expression)
var expression = Expression.new()
if expression.parse(str_expression, vars[0]) != OK:
push_error("Parser: Error on line: " + str(i+1) + ", " + expression.get_error_text())
return {}

var sub_results = other_cache["VARIABLE"].search_all(str_expression)

var vars = []

# Expression does not like '.'
var vars_expression = []

for sub_result in sub_results:
var sub_result_str = sub_result.strings[0]

if !vars.has(sub_result_str):
vars.push_back(sub_result_str)

var var_name_expr = sub_result.get_string("char_tag")

if !var_name_expr.is_empty():
var_name_expr += "_" + sub_result.get_string("var_name")
parse_array.push_back([key, result, expression, vars[1]])

str_expression = str_expression.replace(sub_result_str, var_name_expr)
else:
var_name_expr = sub_result.get_string("var_name")

if !vars_expression.has(var_name_expr):
vars_expression.push_back(var_name_expr)
"SET_VARIABLE":
var str_expression:String = result.get_string("expression")

if str_expression.is_empty():
parse_array.push_back([key, result])
break
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If your str_expression is empty why you do not send an error ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, I last touch this code over a month ago, so maybe I was to change into something and forgot.
I will test with out this if-block and only if find that is really need restore it in proper form.


var vars = get_vars_in_expression(str_expression)
var expression = Expression.new()

if expression.parse(str_expression, vars_expression) != OK:
if expression.parse(str_expression, vars[0]) != OK:
push_error("Parser: Error on line: " + str(i+1) + ", " + expression.get_error_text())
return {}

parse_array.push_back([key, result, expression, vars])
parse_array.push_back([key, result, expression, vars[1]])

_:
parse_array.push_back([key, result])

break

if (not have_find_key):
Expand Down