]> Untitled Git - wolf-seeking-sheep.git/blob - addons/dialogic/Modules/Core/subsystem_expression.gd
Squashed commit of the following:
[wolf-seeking-sheep.git] / addons / dialogic / Modules / Core / subsystem_expression.gd
1 extends DialogicSubsystem
2
3 ## Subsystem that allows executing strings (with the Expression class).
4 ## This is used by conditions and to allow expresions as variables.
5
6
7 #region MAIN METHODS
8 ####################################################################################################
9
10 func execute_string(string:String, default: Variant = null, no_warning := false) -> Variant:
11         # Some methods are not supported by the expression class, but very useful.
12         # Thus they are recreated below and secretly added.
13         string = string.replace('range(', 'd_range(')
14         string = string.replace('len(', 'd_len(')
15         string = string.replace('regex(', 'd_regex(')
16
17
18         var regex: RegEx = RegEx.create_from_string('{([^{}]*)}')
19
20         for res in regex.search_all(string):
21                 var value: Variant = dialogic.VAR.get_variable(res.get_string())
22                 string = string.replace(res.get_string(), var_to_str(value))
23
24         if string.begins_with("{") and string.ends_with('}') and string.count("{") == 1:
25                 string = string.trim_prefix("{").trim_suffix("}")
26
27         var expr := Expression.new()
28
29         var autoloads := []
30         var autoload_names := []
31         for c in get_tree().root.get_children():
32                 autoloads.append(c)
33                 autoload_names.append(c.name)
34
35         if expr.parse(string, autoload_names) != OK:
36                 if not no_warning:
37                         printerr('[Dialogic] Expression "', string, '" failed to parse.')
38                         printerr('           ', expr.get_error_text())
39                         dialogic.print_debug_moment()
40                 return default
41
42         var result: Variant = expr.execute(autoloads, self)
43         if expr.has_execute_failed():
44                 if not no_warning:
45                         printerr('[Dialogic] Expression "', string, '" failed to parse.')
46                         printerr('           ', expr.get_error_text())
47                         dialogic.print_debug_moment()
48                 return default
49         return result
50
51
52 func execute_condition(condition:String) -> bool:
53         if execute_string(condition, false):
54                 return true
55         return false
56
57
58 var condition_modifier_regex := RegEx.create_from_string(r"(?(DEFINE)(?<nobraces>([^{}]|\{(?P>nobraces)\})*))\[if *(?<condition>\{(?P>nobraces)\})(?<truetext>(\\\]|\\\/|[^\]\/])*)(\/(?<falsetext>(\\\]|[^\]])*))?\]")
59 func modifier_condition(text:String) -> String:
60         for find in condition_modifier_regex.search_all(text):
61                 if execute_condition(find.get_string("condition")):
62                         text = text.replace(find.get_string(), find.get_string("truetext").strip_edges())
63                 else:
64                         text = text.replace(find.get_string(), find.get_string("falsetext").strip_edges())
65         return text
66 #endregion
67
68
69 #region HELPERS
70 ####################################################################################################
71 func d_range(a1, a2=null,a3=null,a4=null) -> Array:
72         if !a2:
73                 return range(a1)
74         elif !a3:
75                 return range(a1, a2)
76         elif !a4:
77                 return range(a1, a2, a3)
78         else:
79                 return range(a1, a2, a3, a4)
80
81 func d_len(arg:Variant) -> int:
82         return len(arg)
83
84
85 # Checks if there is a match in a string based on a regex pattern string.
86 func d_regex(input: String, pattern: String, offset: int = 0, end: int = -1) -> bool:
87         var regex: RegEx = RegEx.create_from_string(pattern)
88         regex.compile(pattern)
89         var match := regex.search(input, offset, end)
90         if match:
91                 return true
92         else:
93                 return false
94
95 #endregion