"""comment.py: Hog 4 comment macro interpreter and OSC bridge.""" import configparser import logging from typing import Dict from antlr4 import CommonTokenStream, InputStream, ParseTreeWalker from antlr4.error.ErrorListener import ErrorListener from pythonosc import udp_client from .commentmacro.CommentMacroLexer import CommentMacroLexer from .commentmacro.CommentMacroParser import CommentMacroParser from .OscListener import OscCommentMacroListener __all__ = [ "SyntaxErrorListener", "load_servers", "comment", "WALKER", "LISTENER", ] log = logging.getLogger(__name__) class SyntaxErrorListener(ErrorListener): """An error listener that raises SyntaxError exceptions.""" def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e): raise SyntaxError(f"line {line}:{column} {msg}") def load_servers(file: str = 'server.cfg') -> Dict[int, object]: """Load an ini style configuration file.""" # empty server dictionary servers: Dict[int, object] = {} # open config file config = configparser.ConfigParser(allow_no_value=True) config.read(file) # set up each hog device for name in config.get('network', 'hogs').split(','): try: # move to config section server = config[name.strip().strip('\"')] # read settings addr = server.get("ip", fallback="127.0.0.1") port = server.getint("port", fallback=7001) net = server.getint("net", fallback=1) # osc clients are added to the dictionary with the net # as the key log.info("Adding Hog device at net# %s", net) servers[net] = udp_client.SimpleUDPClient(addr, port) except KeyError as exception: log.error('Error configuring net#%s: %s', net, exception) continue return servers # init reusable walker and listener WALKER: ParseTreeWalker = ParseTreeWalker() LISTENER: OscCommentMacroListener = OscCommentMacroListener() def comment(text: str) -> None: """Process comment macro input.""" # force upper case text = text.upper() # generate text stream input_stream = InputStream(text) # lex the text stream lexer = CommentMacroLexer(input_stream) # get token stream from lexer stream = CommonTokenStream(lexer) # parse the token steam parser = CommentMacroParser(stream) # attach an error handler to the parser parser._listeners.append(SyntaxErrorListener()) try: # get tree from parser tree = parser.prog() # walk the tree WALKER.walk(LISTENER, tree) except SyntaxError as exception: log.debug(exception)