def parse(input_string, parse_as=None): """Attempt to parse a string into a choices dictionary. Args: input_string: The string to parse parse_as: String specifying how to parse `input_string`. Valid values are 'func' or 'url'. Will try all valid values if None. Returns: Dictionary containing the parse results Raises: lark.common.ParseError: Unable to find a valid parsing of `input_string` """ def _parse(_input_string, _parser): try: return FunctionTransformer().transform( _parser.parse(_input_string)) except (GrammarError, LexError, ParseError) as e: raise ParseError(e) if parse_as is not None: return _parse(input_string, parsers[parse_as]) else: for parser in parsers.values(): try: return _parse(input_string, parser) except ParseError: continue raise ParseError('Unable to successfully parse input "%s"' % input_string)
def __getattr__(self, attr: str): """Also parse propositional logic.""" if attr.startswith("pl__"): return getattr(self._pl_transformer, attr[4:]) elif attr in self._pl_imported: return getattr(self._pl_transformer, attr) elif attr.isupper(): raise AttributeError("Terminals should not be parsed") else: raise ParseError("No transformation exists for rule", attr)
def member( self, args: List[Union[Callable[[Transducer], PyLautAtom], str]] ) -> Callable[[PyLautAtom], PyLautAtom]: """ Translates member access on transducer data. Right now all the legal options are hard-coded in. In the future, it might be desirable to translate everything down into direct method calls using the same nomenclature, allowing featuresets / phone subclasses to provide them or not. :param list args: a fetcher function and a string indicated what should be fetched from its result. :returns: Another fetcher function. """ entity = args[0] field = args[1] if isinstance(entity, tuple): entity = entity[1] if field == 'nucleus': def ret(td, f=entity): return f(td).get_nucleus() elif field == 'onset': def ret(td, f=entity): return f(td).get_onset() elif field == 'coda': def ret(td, f=entity): return f(td).get_coda() elif field == 'quality': def get_vowel_quality(td, f=entity): # f(td) must produce a vowel! e = f(td) if isinstance(e, list): vowel = e[0].copy() else: vowel = e.copy() vowel.set_features_false("long") vowel.set_symbol_from_features() return vowel ret = get_vowel_quality elif field == 'is_monosyllable': def ret(td, f=entity): return f(td).is_monosyllable() else: raise ParseError("Unknown field {}!".format(field)) return ret
def _parse(_input_string, _parser): try: return FunctionTransformer().transform( _parser.parse(_input_string)) except (GrammarError, LexError, ParseError) as e: raise ParseError(e)
def relative_expr(self, args): """ This method translates relative position expressions in sound change conditions. It is quite convoluted, due to the fact that there are many different ways to construct a relative expression and argument types may be freely mixed. :param list args: The list of position parameters. :returns: A predicate function on a transducer. """ # First, check if there are word boundaries specified # If yes, check if they are in a legal position. # If still yes, set a flag. conditions = [] wordbreak = None if "#" in args: if args[0] == "#": wordbreak = 1 args = args[1:] elif args[-1] == "#": wordbreak = -1 args = args[:-1] else: raise ParseError("Relative Expr contains '#' that is not at " "the edge of the expression.") this = args.index("_") for i in range(len(args)): pos = i - this arg = args[i] # If the argument is a phoneme, we must unpack it. if isinstance(arg, list): arg = arg[0] if isinstance(arg, tuple): arg = arg[0] if isinstance(arg, str): # If the argument is the current position indicator # and there is a word break specified: add a check whether # the current phoneme is at the correct offset from the # word break. if arg == "_": if wordbreak: if wordbreak > 0: conditions.append(This.is_at_index(Phone, i)) else: relpos = -(len(args) - i) conditions.append(This.is_at_index(Phone, relpos)) # Otherwise, assume the string is a phone written without # slashes. else: for p in arg: conditions.append( This.at(Phone, pos, lambda q, p=p: q.is_symbol(p))) elif isinstance(arg, dict): # If the argument is a dictionary, we have a feature expression # Match the features according to the expression for k, v in arg.items(): conditions.append( This.at(Phone, pos, lambda p, k=k, v=v: p.feature_is(k, v))) else: # The argument is a Phone # Perform by-symbol matching s = arg.symbol conditions.append( This.at(Phone, pos, lambda q, s=s: q.is_symbol(s))) def run_conditions(td, c=conditions): """ Function that closes over the condition list from the relative expression translation. """ for f in c: try: if not f(td): return False except IndexError: return False return True return run_conditions