Update utils/block_relation_builder.py
Browse files- utils/block_relation_builder.py +21 -17
utils/block_relation_builder.py
CHANGED
|
@@ -46,6 +46,9 @@ def generate_blocks_from_opcodes(opcode_counts, all_block_definitions):
|
|
| 46 |
if opcode == "sensing_istouching": # Handle potential old opcode name
|
| 47 |
opcode = "sensing_touchingobject"
|
| 48 |
|
|
|
|
|
|
|
|
|
|
| 49 |
if not opcode or opcode not in all_block_definitions:
|
| 50 |
print(f"Warning: Skipping opcode '{opcode}' (missing or not in definitions).")
|
| 51 |
continue
|
|
@@ -1713,7 +1716,9 @@ def parse_condition(stmt, parent_key, pick_key_func, all_generated_blocks):
|
|
| 1713 |
return {"kind": "block", "block": block_id}
|
| 1714 |
|
| 1715 |
# 5) Touching object: <touching [edge v]?>
|
| 1716 |
-
m_touch = re.fullmatch(r"""\s*<?\s*touching\s*\[\s*(?P<sprite>[^\]]+?)\s*(?:v)?\s*\]\s*\?\s*>?""", s_lower, re.IGNORECASE | re.VERBOSE)
|
|
|
|
|
|
|
| 1717 |
if m_touch:
|
| 1718 |
sprite = m_touch.group('sprite').strip()
|
| 1719 |
val = {'mouse-pointer':'_mouse_', 'edge':'_edge_'}.get(sprite, sprite)
|
|
@@ -1874,7 +1879,7 @@ def classify(line):
|
|
| 1874 |
if l.startswith("repeat until <"): return "control_repeat_until", "c_block"
|
| 1875 |
# Updated regex for stop block to handle different options
|
| 1876 |
#if re.match(r"stop \[(all|this script|other scripts in sprite)\s*v\]", l): return "control_stop", "cap"
|
| 1877 |
-
if re.match(r"stop\s*
|
| 1878 |
if l.startswith("create clone of"): return "control_create_clone_of", "stack"
|
| 1879 |
if l == "delete this clone": return "control_delete_this_clone", "cap"
|
| 1880 |
|
|
@@ -2348,34 +2353,34 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
| 2348 |
info["fields"]["VARIABLE"] = [var_name, None]
|
| 2349 |
if "LIST" in info["fields"]:
|
| 2350 |
m = re.search(r"(?:to|of|in)\s*\[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2351 |
-
if m: info["fields"]["LIST"] = [m.group(1), None]
|
| 2352 |
if "STOP_OPTION" in info["fields"]:
|
| 2353 |
m = re.search(r"stop \[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2354 |
-
if m: info["fields"]["STOP_OPTION"] = [m.group(1), None]
|
| 2355 |
if "STYLE" in info["fields"]:
|
| 2356 |
m = re.search(r"set rotation style \[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2357 |
-
if m: info["fields"]["STYLE"] = [m.group(1), None]
|
| 2358 |
if "DRAG_MODE" in info["fields"]:
|
| 2359 |
m = re.search(r"set drag mode \[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2360 |
-
if m: info["fields"]["DRAG_MODE"] = [m.group(1), None]
|
| 2361 |
if "EFFECT" in info["fields"] and opcode in ["looks_changeeffectby", "looks_seteffectto", "sound_changeeffectby", "sound_seteffectto"]:
|
| 2362 |
m = re.search(r"(?:change|set)\s*\[([^\]]+)\s*v\] effect", stmt_for_parse, re.IGNORECASE)
|
| 2363 |
-
if m: info["fields"]["EFFECT"] = [m.group(1).upper(), None]
|
| 2364 |
if "NUMBER_NAME" in info["fields"] and opcode in ["looks_costumenumbername", "looks_backdropnumbername"]:
|
| 2365 |
m = re.search(r"(?:costume|backdrop)\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2366 |
-
if m: info["fields"]["NUMBER_NAME"] = [m.group(1), None]
|
| 2367 |
if "FRONT_BACK" in info["fields"] and opcode == "looks_gotofrontback":
|
| 2368 |
m = re.search(r"go to\s*\[([^\]]+)\s*v\] layer", stmt_for_parse, re.IGNORECASE)
|
| 2369 |
-
if m: info["fields"]["FRONT_BACK"] = [m.group(1), None]
|
| 2370 |
if "FORWARD_BACKWARD" in info["fields"] and opcode == "looks_goforwardbackwardlayers":
|
| 2371 |
m = re.search(r"go\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2372 |
-
if m: info["fields"]["FORWARD_BACKWARD"] = [m.group(1), None]
|
| 2373 |
if "OPERATOR" in info["fields"] and opcode == "operator_mathop":
|
| 2374 |
m = re.search(r"\[([^\]]+)\s*v\] of", stmt_for_parse, re.IGNORECASE)
|
| 2375 |
-
if m: info["fields"]["OPERATOR"] = [m.group(1).upper(), None]
|
| 2376 |
if "CURRENTMENU" in info["fields"] and opcode == "sensing_current":
|
| 2377 |
m = re.search(r"current\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2378 |
-
if m: info["fields"]["CURRENTMENU"] = [m.group(1).upper(), None]
|
| 2379 |
if "PROPERTY" in info["fields"] and opcode == "sensing_of":
|
| 2380 |
m = re.search(r"\((.+?)\) of", stmt_for_parse, re.IGNORECASE)
|
| 2381 |
if m:
|
|
@@ -2388,16 +2393,16 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
| 2388 |
info["fields"]["PROPERTY"] = [prop_map.get(prop, prop), None]
|
| 2389 |
if "WHENGREATERTHANMENU" in info["fields"] and opcode == "event_whengreaterthan":
|
| 2390 |
m = re.search(r"when\s*\[([^\]]+)\s*v\] >", stmt_for_parse, re.IGNORECASE)
|
| 2391 |
-
if m: info["fields"]["WHENGREATERTHANMENU"] = [m.group(1).upper(), None]
|
| 2392 |
if "KEY_OPTION" in info["fields"] and opcode == "event_whenkeypressed": # For event_whenkeypressed hat block's field
|
| 2393 |
m = re.search(r"when\s*\[([^\]]+)\s*v\] key pressed", stmt_for_parse, re.IGNORECASE)
|
| 2394 |
-
if m: info["fields"]["KEY_OPTION"] = [m.group(1), None]
|
| 2395 |
if "BACKDROP" in info["fields"] and opcode == "event_whenbackdropswitchesto": # For event_whenbackdropswitchesto hat block's field
|
| 2396 |
m = re.search(r"when backdrop switches to\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2397 |
-
if m: info["fields"]["BACKDROP"] = [m.group(1), None]
|
| 2398 |
if "BROADCAST_OPTION" in info["fields"] and opcode == "event_whenbroadcastreceived": # For event_whenbroadcastreceived hat block's field
|
| 2399 |
m = re.search(r"when i receive\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2400 |
-
if m: info["fields"]["BROADCAST_OPTION"] = [m.group(1), None]
|
| 2401 |
|
| 2402 |
# Custom block specific parsing
|
| 2403 |
if opcode == "procedures_definition":
|
|
@@ -2453,7 +2458,6 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
|
|
| 2453 |
info["mutation"]["argumentnames"].append(f"arg{idx+1}") # Placeholder name for mutation
|
| 2454 |
|
| 2455 |
info["inputs"][arg_input_name] = parse_reporter_or_value(arg_val_str, key, pick_key, all_generated_blocks) # Pass current block's key
|
| 2456 |
-
|
| 2457 |
i += 1 # Move to the next line
|
| 2458 |
|
| 2459 |
# Final pass to ensure last blocks have next: None (already handled by stack pops)
|
|
|
|
| 46 |
if opcode == "sensing_istouching": # Handle potential old opcode name
|
| 47 |
opcode = "sensing_touchingobject"
|
| 48 |
|
| 49 |
+
if opcode == "sensing_touchingobject": # Handle potential old opcode name
|
| 50 |
+
opcode = "sensing_touchingobject"
|
| 51 |
+
|
| 52 |
if not opcode or opcode not in all_block_definitions:
|
| 53 |
print(f"Warning: Skipping opcode '{opcode}' (missing or not in definitions).")
|
| 54 |
continue
|
|
|
|
| 1716 |
return {"kind": "block", "block": block_id}
|
| 1717 |
|
| 1718 |
# 5) Touching object: <touching [edge v]?>
|
| 1719 |
+
# m_touch = re.fullmatch(r"""\s*<?\s*touching\s*\[\s*(?P<sprite>[^\]]+?)\s*(?:v)?\s*\]\s*\?\s*>?""", s_lower, re.IGNORECASE | re.VERBOSE)
|
| 1720 |
+
#m_touch = re.fullmatch(r"""\s*<?\s*touching\s*\[\s*(?P<sprite>[^\]]+?)\s*(?:v)?\s*\]\s*\?\s*>?\s*""", s_lower, re.IGNORECASE | re.VERBOSE)
|
| 1721 |
+
m_touch = re.fullmatch(r"""\s*<?\s*touching\s*\[\s*(?P<sprite>[^\]]+?)\s*(?:v)?\s*\]\s*(?:\?)?\s*>?\s*""", s_lower, re.IGNORECASE | re.VERBOSE)
|
| 1722 |
if m_touch:
|
| 1723 |
sprite = m_touch.group('sprite').strip()
|
| 1724 |
val = {'mouse-pointer':'_mouse_', 'edge':'_edge_'}.get(sprite, sprite)
|
|
|
|
| 1879 |
if l.startswith("repeat until <"): return "control_repeat_until", "c_block"
|
| 1880 |
# Updated regex for stop block to handle different options
|
| 1881 |
#if re.match(r"stop \[(all|this script|other scripts in sprite)\s*v\]", l): return "control_stop", "cap"
|
| 1882 |
+
if re.match(r"stop\s*[\[(]?\s*(all|this script|other scripts in sprite)\s*(?:v)?\s*[\])]?$", l, re.IGNORECASE): return "control_stop", "cap"
|
| 1883 |
if l.startswith("create clone of"): return "control_create_clone_of", "stack"
|
| 1884 |
if l == "delete this clone": return "control_delete_this_clone", "cap"
|
| 1885 |
|
|
|
|
| 2353 |
info["fields"]["VARIABLE"] = [var_name, None]
|
| 2354 |
if "LIST" in info["fields"]:
|
| 2355 |
m = re.search(r"(?:to|of|in)\s*\[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2356 |
+
if m: info["fields"]["LIST"] = [m.group(1).strip(), None]
|
| 2357 |
if "STOP_OPTION" in info["fields"]:
|
| 2358 |
m = re.search(r"stop \[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2359 |
+
if m: info["fields"]["STOP_OPTION"] = [m.group(1).strip(), None]
|
| 2360 |
if "STYLE" in info["fields"]:
|
| 2361 |
m = re.search(r"set rotation style \[([^\]]+)\s*v\]", stmt_for_parse)
|
| 2362 |
+
if m: info["fields"]["STYLE"] = [m.group(1).strip(), None]
|
| 2363 |
if "DRAG_MODE" in info["fields"]:
|
| 2364 |
m = re.search(r"set drag mode \[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2365 |
+
if m: info["fields"]["DRAG_MODE"] = [m.group(1).strip(), None]
|
| 2366 |
if "EFFECT" in info["fields"] and opcode in ["looks_changeeffectby", "looks_seteffectto", "sound_changeeffectby", "sound_seteffectto"]:
|
| 2367 |
m = re.search(r"(?:change|set)\s*\[([^\]]+)\s*v\] effect", stmt_for_parse, re.IGNORECASE)
|
| 2368 |
+
if m: info["fields"]["EFFECT"] = [m.group(1).upper().strip(), None]
|
| 2369 |
if "NUMBER_NAME" in info["fields"] and opcode in ["looks_costumenumbername", "looks_backdropnumbername"]:
|
| 2370 |
m = re.search(r"(?:costume|backdrop)\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2371 |
+
if m: info["fields"]["NUMBER_NAME"] = [m.group(1).strip(), None]
|
| 2372 |
if "FRONT_BACK" in info["fields"] and opcode == "looks_gotofrontback":
|
| 2373 |
m = re.search(r"go to\s*\[([^\]]+)\s*v\] layer", stmt_for_parse, re.IGNORECASE)
|
| 2374 |
+
if m: info["fields"]["FRONT_BACK"] = [m.group(1).strip(), None]
|
| 2375 |
if "FORWARD_BACKWARD" in info["fields"] and opcode == "looks_goforwardbackwardlayers":
|
| 2376 |
m = re.search(r"go\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2377 |
+
if m: info["fields"]["FORWARD_BACKWARD"] = [m.group(1).strip(), None]
|
| 2378 |
if "OPERATOR" in info["fields"] and opcode == "operator_mathop":
|
| 2379 |
m = re.search(r"\[([^\]]+)\s*v\] of", stmt_for_parse, re.IGNORECASE)
|
| 2380 |
+
if m: info["fields"]["OPERATOR"] = [m.group(1).upper().strip(), None]
|
| 2381 |
if "CURRENTMENU" in info["fields"] and opcode == "sensing_current":
|
| 2382 |
m = re.search(r"current\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2383 |
+
if m: info["fields"]["CURRENTMENU"] = [m.group(1).upper().strip(), None]
|
| 2384 |
if "PROPERTY" in info["fields"] and opcode == "sensing_of":
|
| 2385 |
m = re.search(r"\((.+?)\) of", stmt_for_parse, re.IGNORECASE)
|
| 2386 |
if m:
|
|
|
|
| 2393 |
info["fields"]["PROPERTY"] = [prop_map.get(prop, prop), None]
|
| 2394 |
if "WHENGREATERTHANMENU" in info["fields"] and opcode == "event_whengreaterthan":
|
| 2395 |
m = re.search(r"when\s*\[([^\]]+)\s*v\] >", stmt_for_parse, re.IGNORECASE)
|
| 2396 |
+
if m: info["fields"]["WHENGREATERTHANMENU"] = [m.group(1).upper().strip(), None]
|
| 2397 |
if "KEY_OPTION" in info["fields"] and opcode == "event_whenkeypressed": # For event_whenkeypressed hat block's field
|
| 2398 |
m = re.search(r"when\s*\[([^\]]+)\s*v\] key pressed", stmt_for_parse, re.IGNORECASE)
|
| 2399 |
+
if m: info["fields"]["KEY_OPTION"] = [m.group(1).strip(), None]
|
| 2400 |
if "BACKDROP" in info["fields"] and opcode == "event_whenbackdropswitchesto": # For event_whenbackdropswitchesto hat block's field
|
| 2401 |
m = re.search(r"when backdrop switches to\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2402 |
+
if m: info["fields"]["BACKDROP"] = [m.group(1).strip(), None]
|
| 2403 |
if "BROADCAST_OPTION" in info["fields"] and opcode == "event_whenbroadcastreceived": # For event_whenbroadcastreceived hat block's field
|
| 2404 |
m = re.search(r"when i receive\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
|
| 2405 |
+
if m: info["fields"]["BROADCAST_OPTION"] = [m.group(1).strip(), None]
|
| 2406 |
|
| 2407 |
# Custom block specific parsing
|
| 2408 |
if opcode == "procedures_definition":
|
|
|
|
| 2458 |
info["mutation"]["argumentnames"].append(f"arg{idx+1}") # Placeholder name for mutation
|
| 2459 |
|
| 2460 |
info["inputs"][arg_input_name] = parse_reporter_or_value(arg_val_str, key, pick_key, all_generated_blocks) # Pass current block's key
|
|
|
|
| 2461 |
i += 1 # Move to the next line
|
| 2462 |
|
| 2463 |
# Final pass to ensure last blocks have next: None (already handled by stack pops)
|