Source code for ase2sprkkr.common.grammar

"""
Various pyparsing grammar elements and a few useful routines.
"""

from contextlib import contextmanager
import pyparsing as pp
from .decorators import cache


[docs] @contextmanager def generate_grammar(): """ Set the pyparsing newline handling and then restore to the original state """ try: old = None kchars = None pe = pp.ParserElement if hasattr(pe, "DEFAULT_WHITE_CHARS"): old = pe.DEFAULT_WHITE_CHARS if hasattr(pp.Keyword, "DEFAULT_KEYWORD_CHARS"): kchars = pp.Keyword.DEFAULT_KEYWORD_CHARS + '-' pe.setDefaultWhitespaceChars(' \t\r') yield finally: if old is not None: pe.setDefaultWhitespaceChars(old) if kchars is not None: pp.Keyword.DEFAULT_KEYWORD_CHARS = kchars
[docs] def replace_whitechars(expr): expr = expr.copy() expr.setWhitespaceChars(' \t\r') return expr
with generate_grammar(): optional_line_end = pp.Suppress(pp.LineEnd() | pp.WordStart() ).setName(' ') """ Grammar for an optinal newline """ line_end = pp.Suppress(pp.LineEnd()).setName('\n') """ Grammar for a required newline """ end_of_file = (pp.Regex(r'[\s]*') + pp.StringEnd()).suppress().setName('<EOF>') """ Grammar for an end of file (ending whitespaces are allowed) """ optional_quote = pp.Optional("'").suppress() """ Grammar for an optional quote """
[docs] def separator_pattern(char): return f'[{char}]' * 11 + '*'
[docs] @cache def separator_grammar(char): """ Pattern for separating sections in an input file """ separator = pp.Regex(separator_pattern(char)).setName(f"{char*10}[{char*4}....]").suppress() return separator
[docs] def delimitedList(expr, delim): """ Delimited list with already suppressed delimiter (or with a in-results-wanted one) """ return expr + pp.ZeroOrMore(delim + expr)
[docs] def addConditionEx(self, condition, message): """ Add check condition to the pyparsing ParseElement, that, if it failed, raise a parse exception with a given message. """ def check_condition(s, loc, tocs): m = message if condition(tocs): return tocs if not isinstance(m, str): m = m(tocs) raise pp.ParseException(s, loc, m) self.addParseAction(check_condition) return self
[docs] def addParseActionEx(self, pa, message = None): """ Add parse action to a given pyparsing ParseElemenet, that, if it raise an exception, fail with a given message """ def parse_action(s, loc, x): try: return pa(x) except Exception as e: if message: msg = f'{message}\n{e}' else: msg = str(e) raise pp.ParseException(s, loc, msg).with_traceback(e.__traceback__) from e self.addParseAction(parse_action)
[docs] class White(pp.White): """ Fix for whitechars in pp.White In Python 3.10, pyparsing.White do not respect default_white_chars. This class fixes this. """
[docs] def __init__(self, white): super().__init__(white) self.setWhitespaceChars('')
pp.ParserElement.addConditionEx = addConditionEx pp.ParserElement.addParseActionEx = addParseActionEx