Source code for knitout_interpreter.knitout_language.Knitout_Parser

"""Parser code for accessing Parglare language support"""
import re

# Use the modern import with fallback
try:
    from importlib.resources import files
except ImportError:
    from importlib_resources import files
import parglare.exceptions
from parglare import Parser, Grammar

import knitout_interpreter
from knitout_interpreter.knitout_language.knitout_actions import action
from knitout_interpreter.knitout_operations.Knitout_Line import Knitout_Line


[docs] class Knitout_Parser: """Parser for reading knitout using the parglare library.""" def __init__(self, debug_grammar: bool = False, debug_parser: bool = False, debug_parser_layout: bool = False) -> None: """Initialize the Knitout parser with optional debugging features. Args: debug_grammar: Enable grammar debugging. Defaults to False. debug_parser: Enable parser debugging. Defaults to False. debug_parser_layout: Enable parser layout debugging. Defaults to False. Raises: FileNotFoundError: If the <knitout.pg> grammar file cannot be located in the package. """ try: pg_resource_stream = files(knitout_interpreter.knitout_language).joinpath('knitout.pg') self._grammar: Grammar = Grammar.from_file(pg_resource_stream, debug=debug_grammar, ignore_case=True) except (FileNotFoundError, AttributeError) as e: raise FileNotFoundError( f"Could not locate 'knitout.pg' in package 'knitout_interpreter.knitout_language'. " f"Please ensure the package is properly installed and the grammar file is included. " f"Original error: {e}" ) from e self._grammar: Grammar = Grammar.from_file(pg_resource_stream, debug=debug_grammar, ignore_case=True) self._set_parser(debug_parser, debug_parser_layout) def _set_parser(self, debug_parser: bool, debug_parser_layout: bool) -> None: """Set up the parser with the current grammar and debugging options. Args: debug_parser: Enable parser debugging. debug_parser_layout: Enable parser layout debugging. """ self._parser: Parser = Parser(self._grammar, debug=debug_parser, debug_layout=debug_parser_layout, actions=action.all) self._parser.knitout_parser = self # make this structure available from actions
[docs] def parse_knitout_to_instructions(self, pattern: str, pattern_is_file: bool = False, reset_parser: bool = True, debug_parser: bool = False, debug_parser_layout: bool = False) -> list[Knitout_Line]: """Parse knitout pattern into a list of instruction objects. Args: pattern: Either a file path or the knitout string to be parsed. pattern_is_file: If True, treat pattern as a file path. Defaults to False. reset_parser: Reset parser to have no prior input. Defaults to True. debug_parser: Enable parser debugging. Defaults to False. debug_parser_layout: Enable parser layout debugging. Defaults to False. Returns: List of knitout instructions created by parsing the given pattern. Raises: parglare.exceptions.ParseError: If there's an error parsing the knitout code. """ codes: list[Knitout_Line] = [] if reset_parser: self._set_parser(debug_parser, debug_parser_layout) if pattern_is_file: with open(pattern, "r") as pattern_file: lines = pattern_file.readlines() else: lines = pattern.splitlines() for i, line in enumerate(lines): if not re.match(r'^\s*$', line): try: code = self._parser.parse(line) except parglare.exceptions.ParseError as e: print(f"Knitout Parsing Error at {i}: {line}") raise e if code is None: continue else: assert isinstance(code, Knitout_Line), f"Expected Knitout Line but got {code}" codes.append(code) return codes
[docs] def parse_knitout(pattern: str, pattern_is_file: bool = False, debug_parser: bool = False, debug_parser_layout: bool = False) -> list[Knitout_Line]: """Execute the parsing code for the parglare parser. This is a convenience function that creates a Knitout_Parser instance and parses the given pattern. Args: pattern: Either a file path or the knitout string to be parsed. pattern_is_file: If True, treat pattern as a file path. Defaults to False. debug_parser: Enable parser debugging. Defaults to False. debug_parser_layout: Enable parser layout debugging. Defaults to False. Returns: List of knitout instructions created by parsing the given pattern. Raises: parglare.exceptions.ParseError: If there's an error parsing the knitout code. FileNotFoundError: If the grammar file or input file cannot be found. """ parser = Knitout_Parser(debug_parser, debug_parser_layout) return parser.parse_knitout_to_instructions(pattern, pattern_is_file, reset_parser=False)