def apply(self, string, patt, evaluation, options): "StringMatchQ[string_, patt_, OptionsPattern[%(name)s]]" py_string = string.get_string_value() if py_string is None: return evaluation.message( "StringMatchQ", "strse", Integer1, Expression("StringMatchQ", string, patt), ) re_patt = to_regex(patt, evaluation, abbreviated_patterns=True) if re_patt is None: return evaluation.message("StringExpression", "invld", patt, Expression("StringExpression", patt)) re_patt = anchor_pattern(re_patt) flags = re.MULTILINE if options["System`IgnoreCase"] == SymbolTrue: flags = flags | re.IGNORECASE if re.match(re_patt, py_string, flags=flags) is None: return SymbolFalse else: return SymbolTrue
def apply_pattern(self, s, patt, expression, evaluation): "StringTrim[s_String, patt_]" text = s.get_string_value() if not text: return s py_patt = to_regex(patt, evaluation) if py_patt is None: return evaluation.message("StringExpression", "invld", patt, expression) if not py_patt.startswith(r"\A"): left_patt = r"\A" + py_patt else: left_patt = py_patt if not py_patt.endswith(r"\Z"): right_patt = py_patt + r"\Z" else: right_patt = py_patt m = re.search(left_patt, text) left = m.end(0) if m else 0 m = re.search(right_patt, text) right = m.start(0) if m else len(text) return String(text[left:right])
def compile(self, pattern, evaluation): re_patt = to_regex(pattern, evaluation) if re_patt is None: evaluation.message('StringExpression', 'invld', pattern, Expression('StringExpression', pattern)) return re_patt = anchor_pattern(re_patt) return re.compile(re_patt, flags=re.IGNORECASE)
def apply_n(self, string, patt, n, evaluation, options): "StringPosition[string_, patt_, n:(_Integer|DirectedInfinity[1]), OptionsPattern[StringPosition]]" expr = Expression("StringPosition", string, patt, n) # check n if n.has_form("DirectedInfinity", 1): py_n = float("inf") else: py_n = n.get_int_value() if py_n is None or py_n < 0: return evaluation.message("StringPosition", "innf", expr, Integer(3)) # check options if options["System`Overlaps"] == SymbolTrue: overlap = True elif options["System`Overlaps"] == SymbolFalse: overlap = False elif options["System`Overlaps"] == Symbol("All"): # TODO evaluation.message("StringPosition", "overall") overlap = True else: overlap = False # unknown options are teated as False # convert patterns if patt.has_form("List", None): patts = patt.get_leaves() else: patts = [patt] re_patts = [] for p in patts: py_p = to_regex(p, evaluation) if py_p is None: return evaluation.message("StringExpression", "invld", p, patt) re_patts.append(py_p) compiled_patts = [re.compile(re_patt) for re_patt in re_patts] # string or list of strings if string.has_form("List", None): py_strings = [s.get_string_value() for s in string.leaves] if None in py_strings: return results = [ self.do_apply(py_string, compiled_patts, py_n, overlap) for py_string in py_strings ] return Expression(SymbolList, *results) else: py_string = string.get_string_value() if py_string is None: return return self.do_apply(py_string, compiled_patts, py_n, overlap)
def apply(self, pattern, evaluation): "Names[pattern_]" headname = pattern.get_head_name() if headname == "System`StringExpression": pattern = re.compile(to_regex(pattern, evaluation)) else: pattern = pattern.get_string_value() if pattern is None: return names = set([]) for full_name in evaluation.definitions.get_matching_names(pattern): short_name = strip_context(full_name) names.add(short_name if short_name not in names else full_name) # TODO: Mathematica ignores contexts when it sorts the list of # names. return Expression("List", *[String(name) for name in sorted(names)])
def apply(self, string, patt, evaluation, options): "StringSplit[string_, patt_, OptionsPattern[%(name)s]]" if string.get_head_name() == "System`List": leaves = [self.apply(s, patt, evaluation, options) for s in string._leaves] return Expression(SymbolList, *leaves) py_string = string.get_string_value() if py_string is None: return evaluation.message( "StringSplit", "strse", Integer1, Expression("StringSplit", string) ) if patt.has_form("List", None): patts = patt.get_leaves() else: patts = [patt] re_patts = [] for p in patts: py_p = to_regex(p, evaluation) if py_p is None: return evaluation.message("StringExpression", "invld", p, patt) re_patts.append(py_p) flags = re.MULTILINE if options["System`IgnoreCase"] == SymbolTrue: flags = flags | re.IGNORECASE result = [py_string] for re_patt in re_patts: result = [t for s in result for t in mathics_split(re_patt, s, flags=flags)] return string_list( SymbolList, [String(x) for x in result if x != ""], evaluation )