-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate-lang.py
executable file
·183 lines (150 loc) · 5.24 KB
/
update-lang.py
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env python3
'''
Script to update the SQF command definitions from the output of:
_allCommands = [];
supportInfo "" apply {
_x splitString ":" params ["_t", "_x"];
if (_t != "t") then {
_x = _x splitString " ";
_command = switch count _x do {
case 1;
case 2: { _x # 0 };
case 3: { _x # 1 };
default {nil};
};
_allCommands pushBackUnique _command;
};
};
_allCommands sort true;
_allCommands = _allCommands apply {
supportInfo format["i:%1", _x]
};
_allCommands
'''
import ast
from typing import List
nullary_commands = []
unary_commands = []
binary_commands = []
def nullary(command: str, return_type: str) -> str:
return f"{{\"{command}\", Type::{return_type}}}"
def unary(command: str, return_type: str, right_type: str) -> str:
return f"{{\"{command}\", UnaryCommand(Type::{right_type}, Type::{return_type})}}"
def binary(command: str, return_type: str, left_type: str, right_type: str) -> str:
return f"{{\"{command}\", BinaryCommand(Type::{left_type}, Type::{right_type}, Type::{return_type})}}"
def get_types(type: str) -> List[str]:
types = type.split(",")
# bool is reserved
if ("bool" in types):
types.remove("bool")
types.append("boolean")
# exception is reserved
if ("exception" in types):
types.remove("exception")
types.append("exception_type")
# for is reserved
if ("for" in types):
types.remove("for")
types.append("for_type")
# if is reserved
if ("if" in types):
types.remove("if")
types.append("if_type")
# namespace is reserved
if ("namespace" in types):
types.remove("namespace")
types.append("name_space")
# switch is reserved
if ("switch" in types):
types.remove("switch")
types.append("switch_type")
# while is reserved
if ("while" in types):
types.remove("while")
types.append("while_type")
# with is reserved
if ("with" in types):
types.remove("with")
types.append("with_type")
# nan is covered by scalar
try:
types.remove("nan")
finally:
return types
# Inject special non-command for parsing use
binary_commands.append(binary(":", "any", "switch_type", "code"))
# By evaluating the SQF array output as a Python literal a list is easily produced
with open("supportInfo.out", "r") as file:
supportInfo = ast.literal_eval(
# Remove any newlines that would break Python string literals
" ".join(
file.read().split("\n")
)
# Remove doubled doubled up quotations
.replace("\"\"\"\"", "")
# Remove double quotations at the end of a string
.replace("\"\"\"", "\"")
# Remove regular doubled quotations
.replace("\"\"", "")
# Fix empty strings (twice for overlapping patterns)
.replace(",,", ",\"\",")
.replace(",,", ",\"\",")
# Escape escape character
.replace("\\", "\\\\")
# Want everything lowercase to match my C++
.lower()
)
for command in supportInfo:
# Each command has variants, each varient can have multiple return, left and right types
for [type, command, _, _, _, _, return_type, left_type, right_type, _] in command:
# Multiple return types treated as any
return_types = get_types(return_type)
if (len(return_types) > 1):
return_type = "any"
else:
return_type = return_types[0]
if (type == "n"):
nullary_commands.append(nullary(command, return_type))
elif (type == "u"):
for type in get_types(right_type):
unary_commands.append(unary(command, return_type, type))
elif (type == "b"):
left_types = get_types(left_type)
right_types = get_types(right_type)
for ltype in left_types:
for rtype in right_types:
binary_commands.append(binary(command, return_type, ltype, rtype))
with open("src/sqf/nullary_keywords.h", "w") as file:
file.write("#pragma once\n"
"#include <string>\n"
"#include <unordered_map>\n\n"
'#include "./sqf_type.h"\n\n'
"namespace SQF {\n\n"
"const std::unordered_map<std::string, Type> Nullary_Keywords{\n"
)
file.writelines([f" {cmd},\n" for cmd in nullary_commands])
file.write("};\n\n}\n")
with open("src/sqf/unary_keywords.h", "w") as file:
file.write("#pragma once\n"
"#include <string>\n"
"#include <unordered_map>\n\n"
'#include "./sqf_command.h"\n'
'#include "./sqf_type.h"\n\n'
"namespace SQF {\n\n"
"const std::unordered_multimap<std::string, UnaryCommand> "
"Unary_Keywords{\n"
)
file.writelines([f" {cmd},\n" for cmd in unary_commands])
file.write("};\n\n}\n")
with open("src/sqf/binary_keywords.h", "w") as file:
file.write("#pragma once\n"
"#include <string>\n"
"#include <unordered_map>\n\n"
'#include "./sqf_command.h"\n'
'#include "./sqf_type.h"\n\n'
"namespace SQF {\n\n"
"const std::unordered_multimap<std::string, BinaryCommand> "
"Binary_Keywords{\n"
)
file.writelines([f" {cmd},\n" for cmd in binary_commands])
file.write("};\n\n}\n")