- Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstring_parser.py
More file actions
Latest commit
163 lines (128 loc) · 5.29 KB
/
Copy pathstring_parser.py
File metadata and controls
163 lines (128 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#String Building algorithm for the Overwatch Workshop
#
#Heavily inspired by Deltins ParseString algorithm
#https://github.com/ItsDeltin/Overwatch-Script-To-Workshop/blob/91f6d89cae2dda77d40139a589c22077def7654f/Deltinteger/Deltinteger/Elements/Values.cs#L729
#Parts copied are used with permission.
importlogging
importre
classStringParser():
SYMBOLS="-></*-+=()!?"
PARAM_REPLACE_RE=re.compile("(\\\\{[0-9]+?\\\\})")
PARAM_MATCH_RE=re.compile("^\\{([0-9]+?)\\}")
PARAM_ONLY_RE=re.compile("^\\{([0-9]+?)\\}$")
logger=logging.getLogger("OS.StringParser")
def__init__(self, db_file="res/strings.txt"):
self.words= []
self.us_words= []
ifdb_file:
self.loadWords(db_file)
defloadWords(self, path):
"""
Load words from a file.
"""
withopen(path, "r") asf:
forlineinf.readlines():
ifline.startswith("//"):
continue
self.words.append(line.strip("\n").lower())
self.sort()
defsort(self):
"""
Sort the internal list of words after
certain criteria.
"""
#Right so I don't have fancy incremental sorting like C# does.
#What I *can* do is split the list into multiple lists, then merge
#TODO: temporary fix
foriinself.words:
if"_"ini:
j=i.replace("_", " ")
self.us_words.append((i, j))
hasParam= []
foriinself.words[:]:
if"{0}"ini:
hasParam.append(i)
self.words.remove(i)
hasParamAndSymbol= []
foriinhasParam[:]:
forcharinself.SYMBOLS:
ifcharini:
hasParamAndSymbol.append(i)
hasParam.remove(i)
break
hasSymbol= []
foriinself.words[:]:
forcharinself.SYMBOLS:
ifcharini:
hasSymbol.append(i)
self.words.remove(i)
break
#Sorting key function
deff(x):
returnlen(x)
hasParam.sort(key=f)
hasParamAndSymbol.sort(key=f)
hasSymbol.sort(key=f)
self.words.sort(key=f)
self.words.extend(hasSymbol)
self.words.extend(hasParam)
self.words.extend(hasParamAndSymbol)
self.words.reverse()
defparse(self, s, params, depth=0):
"""
Parse a string into a value understood by OWW.
s should be an instance of str.
You can specify parameters inside your string using
the {n} syntax. Parameters will be substituted in order
of occurance.
If s contains words or phrases not recognized by the parser,
ValueError is raised.
If params contains more items than s has parameters, the remaining
items are silently dropped.
If params contains less items than s has parameters, TypeError is raised.
The returned value will be a string consisting of one or multiple calls
to the String() OWW function.
"""
final_string=""
#TODO: temporary fix
ifnotdepth:
fortemplate, phraseinself.us_words:
s=s.replace(phrase, template)
#special case for when the string passed to the parse() method
#is literally just "{n}"
m=self.PARAM_ONLY_RE.fullmatch(s)
ifmisnotNone:
returnparams[int(m.group(1))]
fortemplateinself.words:
temp_re="^%s$"%re.sub(self.PARAM_REPLACE_RE, "(.+)", re.escape(template))
self.logger.debug("Testing string template '%s' (-> RE template '%s')..."% (template, temp_re))
match=re.match(temp_re, s)
ifmatchisnotNone:
try:
self.logger.debug("Match found: %s"%template)
#TODO: Temporary fix
#string_args = ['"%s"' % template]
string_args= ['"%s"'%template.replace("_", " ")]
#check parameters
forgroupinmatch.groups():
#is parameter formatted?
self.logger.debug("Parsing group '%s'..."%group)
paramStr=re.fullmatch(self.PARAM_MATCH_RE, group)
ifparamStr:
#substitute parameter
try:
string_args.append(params[int(paramStr.group(1))])
exceptIndexError:
raiseTypeError("Not enough arguments to format string.")
else:
#keep parsing
string_args.append(self.parse(group, params))
string_args.extend(["null"] * (4-len(string_args)))
final_string+="String(%s)"%", ".join(string_args)
break
exceptValueErrorase:
self.logger.debug("%s. Trying next template..."%str(e))
continue
else:
raiseValueError("Can't match string '%s': No matching template found."%s)
returnfinal_string