3
3
# Author: Dave Bailey (dbisu, @daveisu)
4
4
#
5
5
# TODO: ADD support for the following:
6
- # IF THEN ELSE
7
6
# Add jitter
8
7
# Add LED functionality
9
8
71
70
numbers = "0123456789"
72
71
specialChars = "!@#$%^&*()"
73
72
73
+ class IF :
74
+ def __init__ (self , condition , codeIter ):
75
+ self .condition = condition
76
+ self .codeIter = list (codeIter )
77
+ self .lastIfResult = None
78
+
79
+ def _exitIf (self ):
80
+ _depth = 0
81
+ for line in self .codeIter :
82
+ line = self .codeIter .pop (0 )
83
+ line = line .strip ()
84
+ if line .upper ().startswith ("END_IF" ):
85
+ _depth -= 1
86
+ elif line .upper ().startswith ("IF" ):
87
+ _depth += 1
88
+ if _depth < 0 :
89
+ print ("No else, exiting" + str (list (self .codeIter )))
90
+ break
91
+ return (self .codeIter )
92
+
93
+ def runIf (self ):
94
+ if isinstance (self .condition , str ):
95
+ self .lastIfResult = evaluateExpression (self .condition )
96
+ elif isinstance (self .condition , bool ):
97
+ self .lastIfResult = self .condition
98
+ else :
99
+ raise ValueError ("Invalid condition type" )
100
+
101
+ # print(f"condition {self.condition} result is {self.lastIfResult} since \"$VAR\" is {variables["$VAR"]}, code is {self.codeIter}")
102
+ depth = 0
103
+ for line in self .codeIter :
104
+ line = self .codeIter .pop (0 )
105
+ line = line .strip ()
106
+ if line == "" :
107
+ continue
108
+ # print(line)
109
+
110
+ if line .startswith ("IF" ):
111
+ depth += 1
112
+ elif line .startswith ("END_IF" ):
113
+ if depth == 0 :
114
+ return (self .codeIter , - 1 )
115
+ depth -= 1
116
+
117
+ elif line .startswith ("ELSE" ) and depth == 0 :
118
+ # print(f"ELSE LINE {line}, lastIfResult: {self.lastIfResult}")
119
+ if self .lastIfResult is False :
120
+ line = line [4 :].strip () # Remove 'ELSE' and strip whitespace
121
+ if line .startswith ("IF" ):
122
+ nestedCondition = _getIfCondition (line )
123
+ # print(f"nested IF {nestedCondition}")
124
+ self .codeIter , self .lastIfResult = IF (nestedCondition , self .codeIter ).runIf ()
125
+ if self .lastIfResult == - 1 or self .lastIfResult == True :
126
+ # print(f"self.lastIfResult {self.lastIfResult}")
127
+ return (self .codeIter , True )
128
+ else :
129
+ return IF (True , self .codeIter ).runIf () #< Regular ELSE block
130
+ else :
131
+ self ._exitIf ()
132
+ break
133
+
134
+ # Process regular lines
135
+ elif self .lastIfResult :
136
+ # print(f"running line {line}")
137
+ self .codeIter = list (parseLine (line , self .codeIter ))
138
+ # print("end of if")
139
+ return (self .codeIter , self .lastIfResult )
140
+
141
+ def _getIfCondition (line ):
142
+ return str (line )[2 :- 4 ].strip ()
143
+
144
+ def _isCodeBlock (line ):
145
+ line = line .upper ().strip ()
146
+ if line .startswith ("IF" ) or line .startswith ("WHILE" ):
147
+ return True
148
+ return False
149
+
150
+ def _getCodeBlock (linesIter ):
151
+ """Returns the code block starting at the given line."""
152
+ code = []
153
+ depth = 1
154
+ for line in linesIter :
155
+ line = line .strip ()
156
+ if line .upper ().startswith ("END_" ):
157
+ depth -= 1
158
+ elif _isCodeBlock (line ):
159
+ depth += 1
160
+ if depth <= 0 :
161
+ break
162
+ code .append (line )
163
+ return code
164
+
74
165
def evaluateExpression (expression ):
75
166
"""Evaluates an expression with variables and returns the result."""
76
167
# Replace variables (e.g., $FOO) in the expression with their values
@@ -82,6 +173,9 @@ def evaluateExpression(expression):
82
173
83
174
return eval (expression , {}, variables )
84
175
176
+ def deepcopy (List ):
177
+ return (List [:])
178
+
85
179
def convertLine (line ):
86
180
commands = []
87
181
# print(line)
@@ -134,7 +228,6 @@ def replaceDefines(line):
134
228
135
229
def parseLine (line , script_lines ):
136
230
global defaultDelay , variables , functions , defines
137
- print (line )
138
231
line = line .strip ()
139
232
line = line .replace ("$_RANDOM_INT" , str (random .randint (int (variables .get ("$_RANDOM_MIN" , 0 )), int (variables .get ("$_RANDOM_MAX" , 65535 )))))
140
233
line = replaceDefines (line )
@@ -143,7 +236,7 @@ def parseLine(line, script_lines):
143
236
elif line .startswith ("REM_BLOCK" ):
144
237
while line .startswith ("END_REM" ) == False :
145
238
line = next (script_lines ).strip ()
146
- print (line )
239
+ # print(line)
147
240
elif (line [0 :3 ] == "REM" ):
148
241
pass
149
242
elif line .startswith ("HOLD" ):
@@ -190,7 +283,8 @@ def parseLine(line, script_lines):
190
283
elif (line [0 :6 ] == "STRING" ):
191
284
sendString (replaceVariables (line [7 :]))
192
285
elif (line [0 :5 ] == "PRINT" ):
193
- print ("[SCRIPT]: " + line [6 :])
286
+ line = replaceVariables (line [6 :])
287
+ print ("[SCRIPT]: " + line )
194
288
elif (line [0 :6 ] == "IMPORT" ):
195
289
runScript (line [7 :])
196
290
elif (line [0 :13 ] == "DEFAULT_DELAY" ):
@@ -250,26 +344,30 @@ def parseLine(line, script_lines):
250
344
defineValue = line [valueLocation + 1 :]
251
345
defines [defineName ] = defineValue
252
346
elif line .startswith ("FUNCTION" ):
347
+ # print("ENTER FUNCTION")
253
348
func_name = line .split ()[1 ]
254
349
functions [func_name ] = []
255
350
line = next (script_lines ).strip ()
256
351
while line != "END_FUNCTION" :
257
352
functions [func_name ].append (line )
258
353
line = next (script_lines ).strip ()
259
354
elif line .startswith ("WHILE" ):
260
- condition = re .search (r'\((.*?)\)' , line ).group (1 )
261
- var_name , _ , condition_value = condition .split ()
262
- condition_value = int (condition_value )
263
- loop_code = []
264
- line = next (script_lines ).strip ()
265
- while line != "END_WHILE" :
266
- if not (line .startswith ("WHILE" )):
267
- loop_code .append (line )
268
- line = next (script_lines ).strip ()
269
- while variables [var_name ] > condition_value :
270
- for loop_line in loop_code :
271
- parseLine (loop_line , {})
272
- variables [var_name ] -= 1
355
+ # print("ENTER WHILE LOOP")
356
+ condition = line [5 :].strip ()
357
+ loopCode = list (_getCodeBlock (script_lines ))
358
+ while evaluateExpression (condition ) == True :
359
+ currentIterCode = deepcopy (loopCode )
360
+ print (loopCode )
361
+ while currentIterCode :
362
+ loopLine = currentIterCode .pop (0 )
363
+ currentIterCode = list (parseLine (loopLine , iter (currentIterCode ))) #< very inefficient, should be replaced later.
364
+
365
+ elif line .upper ().startswith ("IF" ):
366
+ # print("ENTER IF")
367
+ script_lines , ret = IF (_getIfCondition (line ), script_lines ).runIf ()
368
+ print (f"IF returned { ret } code" )
369
+ elif line .upper ().startswith ("END_IF" ):
370
+ pass
273
371
elif line == "RANDOM_LOWERCASE_LETTER" :
274
372
sendString (random .choice (letters ))
275
373
elif line == "RANDOM_UPPERCASE_LETTER" :
@@ -311,6 +409,8 @@ def parseLine(line, script_lines):
311
409
parseLine (func_line , iter (functions [line ]))
312
410
else :
313
411
runScriptLine (line )
412
+
413
+ return (script_lines )
314
414
315
415
kbd = Keyboard (usb_hid .devices )
316
416
consumerControl = ConsumerControl (usb_hid .devices )
0 commit comments