Files
konabot/konabot/plugins/marchtoy/command.py
bk_office cf52ea683b regex fix
2026-04-27 19:46:10 +08:00

63 lines
1.7 KiB
Python

"""
raymarch toy
usage: march <scene1> <scene2> ... <sceneN>
<scene> ::= <scene> "." <command>
| <command>
<command> ::= <id>
| <id> "(" <args> ")"
example:
march cube.pos(0, 0, 0).color(red) cam(1.0).pos(1, 1, 1).lookat(0, 0, 0)
"""
from dataclasses import dataclass
import regex as re
from dataclasses import dataclass
@dataclass
class Command:
id: str
args: list[str]
class CommandChainParser:
CHAIN_PATTERN = r"^(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?)(\.(?1))*)"
def __init__(self, _command_chain: str) -> None:
self.command_chain = _command_chain
def __iter__(self):
return self
def __next__(self):
if query := re.match(CommandChainParser.CHAIN_PATTERN, self.command_chain):
cmd_chain = query[0]
self.command_chain = self.command_chain[len(cmd_chain) + 1 :]
return cmd_chain
raise StopIteration
class CommandParser:
CMD_PATTERN = r"^(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?))"
ID_PATTERN = r"^[a-zA-Z]+(?=\(|\.|$)"
def __init__(self, _command: str) -> None:
self.command = _command
def __iter__(self):
return self
def __next__(self):
if query := re.match(CommandParser.CMD_PATTERN, self.command):
cmd = query[0]
if cmd_id_qry := re.match(CommandParser.ID_PATTERN, cmd):
cmd_id = cmd_id_qry[0]
self.command = self.command[len(cmd) + 1 :]
cmd_args = cmd[len(cmd_id) + 1 : -1]#.replace(" ", "").split(",")
# while "" in cmd_args:
# cmd_args.remove("")
return Command(cmd_id, cmd_args)
raise StopIteration