def check(self, expr1, expr2): if isinstance(expr1, six.string_types): expr1 = parse(expr1) if isinstance(expr2, six.string_types): expr2 = parse(expr2) self.assertTrue(expr1.same(expr2))
def check(self, expr1, expr2): if isinstance(expr1, basestring): expr1 = parse(expr1) if isinstance(expr2, basestring): expr2 = parse(expr2) self.assertTrue(expr1.same(expr2))
def check(self, expr1, expr2): if isinstance(expr1, six.string_types): expr1 = parse(expr1) if isinstance(expr2, six.string_types): expr2 = parse(expr2) if expr1 is None: self.assertTrue(expr2 is None) else: self.assertTrue(expr1.same(expr2))
def test_CompoundExpression(self): self.check('f[a;\nb]', 'f[CompoundExpression[a, b]]') self.check('f[a;\nb;\nc;]', 'f[CompoundExpression[a, b, c, Null]]') self.check('f[a;\nb;\nc;\n]', 'f[CompoundExpression[a, b, c, Null]]') self.check('a;^b', 'Power[CompoundExpression[a, Null], b]') feeder = MultiLineFeeder('a;\n^b') self.compare(parse(definitions, feeder), self.parse('CompoundExpression[a, Null]')) self.assertRaises(InvalidSyntaxError, lambda f: parse(definitions, f), feeder)
def test_CompoundExpression(self): self.check("f[a;\nb]", "f[CompoundExpression[a, b]]") self.check("f[a;\nb;\nc;]", "f[CompoundExpression[a, b, c, Null]]") self.check("f[a;\nb;\nc;\n]", "f[CompoundExpression[a, b, c, Null]]") self.check("a;^b", "Power[CompoundExpression[a, Null], b]") feeder = MultiLineFeeder("a;\n^b") self.compare(parse(definitions, feeder), self.parse("CompoundExpression[a, Null]")) self.assertRaises(InvalidSyntaxError, lambda f: parse(definitions, f), feeder)
def apply(self, seq, evaluation): "ToExpression[seq__]" # Organise Arguments py_seq = seq.get_sequence() if len(py_seq) == 1: (inp, form, head) = (py_seq[0], Symbol("InputForm"), None) elif len(py_seq) == 2: (inp, form, head) = (py_seq[0], py_seq[1], None) elif len(py_seq) == 3: (inp, form, head) = (py_seq[0], py_seq[1], py_seq[2]) else: assert len(py_seq) > 3 # 0 case handled by apply_empty evaluation.message( "ToExpression", "argb", "ToExpression", Integer(len(py_seq)), Integer1, Integer(3), ) return # Apply the different forms if form == Symbol("InputForm"): if isinstance(inp, String): # TODO: turn the below up into a function and call that. s = inp.get_string_value() short_s = s[:15] + "..." if len(s) > 16 else s with io.StringIO(s) as f: f.name = """ToExpression['%s']""" % short_s feeder = MathicsFileLineFeeder(f) while not feeder.empty(): try: query = parse(evaluation.definitions, feeder) except TranslateError: return SymbolFailed finally: feeder.send_messages(evaluation) if query is None: # blank line / comment continue result = query.evaluate(evaluation) else: result = inp else: evaluation.message("ToExpression", "interpfmt", form) return # Apply head if present if head is not None: result = Expression(head, result).evaluate(evaluation) return result
def parse_feeder(self, feeder): 'Parse a single expression from feeder and print the messages.' from mathics.core.parser import parse, TranslateError try: result = parse(self.definitions, feeder) except TranslateError as exc: self.recursion_depth = 0 self.stopped = False result = None feeder.send_messages(self) return result
def parse(self, query, timeout=None): 'parse a single line and capture the exceptions as messages' from mathics.core.parser import parse, TranslateError try: expr = parse(query, self.definitions) except TranslateError as exc: self.recursion_depth = 0 self.stopped = False self.message('Syntax', exc.msg, *exc.args) return [] return [expr]
def apply_int(self, n, prop, evaluation): "ElementData[n_?IntegerQ, prop_]" from mathics.core.parser import parse py_n = n.to_python() py_prop = prop.to_python() # Check element specifier n or "name" if isinstance(py_n, int): if not 1 <= py_n <= 118: evaluation.message("ElementData", "noent", n) return elif isinstance(py_n, six.string_types): pass else: evaluation.message("ElementData", "noent", n) return # Check property specifier if isinstance(py_prop, six.string_types): py_prop = str(py_prop) if py_prop == '"Properties"': result = [] for i, p in enumerate(_ELEMENT_DATA[py_n]): if p not in ["NOT_AVAILABLE", "NOT_APPLICABLE", "NOT_KNOWN"]: result.append(_ELEMENT_DATA[0][i]) return from_python(sorted(result)) if not (isinstance(py_prop, six.string_types) and py_prop[0] == py_prop[-1] == '"' and py_prop.strip('"') in _ELEMENT_DATA[0]): evaluation.message("ElementData", "noprop", prop) return iprop = _ELEMENT_DATA[0].index(py_prop.strip('"')) result = _ELEMENT_DATA[py_n][iprop] if result == "NOT_AVAILABLE": return Expression("Missing", "NotAvailable") if result == "NOT_APPLICABLE": return Expression("Missing", "NotApplicable") if result == "NOT_KNOWN": return Expression("Missing", "Unknown") result = parse(result, evaluation.definitions) if isinstance(result, Symbol): result = String(strip_context(result.get_name())) return result
def __init__(self, input=None, definitions=None, timeout=None, out_callback=None, format='text', catch_interrupt=True): from mathics.core.definitions import Definitions if definitions is None: definitions = Definitions() self.definitions = definitions self.recursion_depth = 0 self.timeout = False self.stopped = False self.out = [] self.out_callback = out_callback self.listeners = {} self.options = None self.quiet_all = False self.quiet_messages = set() self.format = format queries = [] last_parse_error = None if input is not None: from mathics.core.parser import parse, TranslateError lines = input.splitlines() query = '' for line in lines: if line: query += line try: expression = parse(query) if expression is not None: queries.append(expression) query = '' last_parse_error = None except TranslateError, exc: last_parse_error = exc else: query += ' '
def get_functions(self, prefix='apply'): from mathics.core.parser import parse for name in dir(self): if name.startswith(prefix): function = getattr(self, name) pattern = function.__doc__ m = re.match(r'([\w,]+)\:\s*(.*)', pattern) if m is not None: attrs = m.group(1).split(',') pattern = m.group(2) else: attrs = [] pattern = pattern % {'name': self.get_name()} pattern = parse(pattern) if attrs: yield (attrs, pattern), function else: yield (pattern, function)
def parse_lines(lines, definitions): ''' Given some lines of code try to construct a list of expressions. In the case of incomplete lines append more lines until a complete expression is found. If the end is reached and no complete expression is found then reraise the exception. We use a generator so that each expression can be evaluated (as the parser is dependent on defintions and evaluation may change the definitions). ''' query = '' lines = lines.splitlines() incomplete_exc = None for line in lines: if not line: query += ' ' continue query += line if query.endswith('\\'): query = query.rstrip('\\') incomplete_exc = IncompleteSyntaxError(len(query)-1) continue try: expression = parse(definitions, SingleLineFeeder(query)) except IncompleteSyntaxError as exc: incomplete_exc = exc else: if expression is not None: yield expression query = '' incomplete_exc = None if incomplete_exc is not None: # ran out of lines raise incomplete_exc raise StopIteration
def parse_lines(lines, definitions): ''' Given some lines of code try to construct a list of expressions. In the case of incomplete lines append more lines until a complete expression is found. If the end is reached and no complete expression is found then reraise the exception. We use a generator so that each expression can be evaluated (as the parser is dependent on defintions and evaluation may change the definitions). ''' query = '' lines = lines.splitlines() incomplete_exc = None for line in lines: if not line: query += ' ' continue query += line if query.endswith('\\'): query = query.rstrip('\\') incomplete_exc = IncompleteSyntaxError(len(query) - 1) continue try: expression = parse(definitions, SingleLineFeeder(query)) except IncompleteSyntaxError as exc: incomplete_exc = exc else: if expression is not None: yield expression query = '' incomplete_exc = None if incomplete_exc is not None: # ran out of lines raise incomplete_exc raise StopIteration
def apply(self, seq, evaluation): 'ToExpression[seq__]' # Organise Arguments py_seq = seq.get_sequence() if len(py_seq) == 1: (inp, form, head) = (py_seq[0], Symbol('InputForm'), None) elif len(py_seq) == 2: (inp, form, head) = (py_seq[0], py_seq[1], None) elif len(py_seq) == 3: (inp, form, head) = (py_seq[0], py_seq[1], py_seq[2]) else: assert len(py_seq) > 3 # 0 case handled by apply_empty evaluation.message('ToExpression', 'argb', 'ToExpression', Integer(len(py_seq)), Integer(1), Integer(3)) return # Apply the differnet forms if form == Symbol('InputForm'): if isinstance(inp, String): from mathics.core.parser import parse, ParseError try: result = parse( inp.get_string_value(), evaluation.definitions) except ParseError: evaluation.message('ToExpression', 'sntxi', String('')) return Symbol('$Failed') else: result = inp else: evaluation.message('ToExpression', 'interpfmt', form) return # Apply head if present if head is not None: result = Expression(head, result).evaluate(evaluation) return result
def benchmark_parse(expression_string): print " '{0}'".format(truncate_line(expression_string)) timeit(lambda: parse(expression_string))
def benchmark_expression(expression_string): print " '{0}'".format(expression_string) expr = parse(expression_string) timeit(lambda: expr.evaluate(evaluation))
def benchmark_format(section_name): print " '{0}'".format(expression_string) expr = parse(expression_string) timeit(lambda: expr.default_format(evaluation, "FullForm"))
def testNone(self): self.assertIs(parse(''), None) self.assertIs(parse('(*fdasf *)'), None)
def parse(self, code): return parse(definitions, SingleLineFeeder(code))
def benchmark_format(expression_string): print(" '{0}'".format(expression_string)) expr = parse(definitions, SingleLineFeeder(expression_string)) timeit(lambda: expr.default_format(evaluation, "FullForm"))
def benchmark_parse(expression_string): print(" '{0}'".format(truncate_line(expression_string))) timeit(lambda: parse(definitions, SingleLineFeeder(expression_string)))
def evaluate(self, str_expression, timeout=None, form=None): expr = parse(self.definitions, MathicsSingleLineFeeder(str_expression)) if form is None: form = self.form self.last_result = expr.evaluate(self.evaluation) return self.last_result
def main(): argparser = argparse.ArgumentParser( prog='mathics', usage='%(prog)s [options] [FILE]', add_help=False, description="Mathics is a general-purpose computer algebra system.", epilog="""Please feel encouraged to contribute to Mathics! Create your own fork, make the desired changes, commit, and make a pull request.""") argparser.add_argument( 'FILE', nargs='?', type=argparse.FileType('r'), help='execute commands from FILE') argparser.add_argument( '--help', '-h', help='show this help message and exit', action='help') argparser.add_argument( '--persist', help='go to interactive shell after evaluating FILE or -e', action='store_true') argparser.add_argument( '--quiet', '-q', help='don\'t print message at startup', action='store_true') argparser.add_argument( '-script', help='run a mathics file in script mode', action='store_true') argparser.add_argument( '--execute', '-e', action='append', metavar='EXPR', help='evaluate EXPR before processing any input files (may be given ' 'multiple times)') argparser.add_argument( '--colors', nargs='?', help='interactive shell colors') argparser.add_argument( '--no-completion', help="disable tab completion", action='store_true') argparser.add_argument( '--no-readline', help="disable line editing (implies --no-completion)", action='store_true') argparser.add_argument( '--version', '-v', action='version', version='%(prog)s ' + __version__) args = argparser.parse_args() quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-D' definitions = Definitions(add_builtin=True) definitions.set_ownvalue('$Line', Integer(0)) # Reset the line number shell = TerminalShell( definitions, args.colors, want_readline=not(args.no_readline), want_completion=not(args.no_completion)) if not (args.quiet or args.script): print() print(version_string + '\n') print(license_string + '\n') print("Quit by pressing {0}\n".format(quit_command)) if args.execute: for expr in args.execute: print(shell.get_in_prompt() + expr) evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) exprs = evaluation.parse(expr) results = evaluation.evaluate(exprs, timeout=settings.TIMEOUT) shell.print_results(results) if not args.persist: return if args.FILE is not None: lines = args.FILE.readlines() if args.script and lines[0].startswith('#!'): lines[0] = '' results = [] query_gen = parse_lines(lines, shell.definitions) evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) try: for query in query_gen: results.extend(evaluation.evaluate([query], timeout=settings.TIMEOUT)) except TranslateError as exc: evaluation.recursion_depth = 0 evaluation.stopped = False evaluation.message('Syntax', exc.msg, *exc.args) except (KeyboardInterrupt): print('\nKeyboardInterrupt') except (SystemExit, EOFError): print("\n\nGood bye!\n") if not args.persist: return total_input = "" while True: try: evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) line = shell.read_line(shell.get_in_prompt(continued=total_input != '')) total_input += line try: query = parse(total_input, shell.definitions) except TranslateError as exc: if line == '' or not isinstance(exc, IncompleteSyntaxError): evaluation.message('Syntax', exc.msg, *exc.args) total_input = "" continue total_input = "" if query is None: continue results = evaluation.evaluate([query], timeout=settings.TIMEOUT) shell.print_results(results) except (KeyboardInterrupt): print('\nKeyboardInterrupt') except (SystemExit, EOFError): print("\n\nGood bye!\n") break
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import unittest from mathics.core.expression import Expression, Integer, Rational, Symbol from mathics.core.definitions import Definitions from mathics.core.evaluation import Evaluation from mathics.core.parser import SingleLineFeeder, parse definitions = Definitions(add_builtin=True) for i in range(1, 4): evaluation = Evaluation(definitions=definitions, catch_interrupt=False) expr = parse(definitions, SingleLineFeeder(f"<< GS{i}.m")) expr.evaluate(evaluation)
def test_Span(self): self.check('a;;^b', 'Power[Span[a, All], b]') feeder = MultiLineFeeder('a;;\n^b') self.compare(parse(definitions, feeder), self.parse('Span[a, All]')) self.assertRaises(InvalidSyntaxError, lambda f: parse(definitions, f), feeder)
def benchmark_format(expression_string): print " '{0}'".format(expression_string) expr = parse(expression_string) timeit(lambda: expr.default_format(evaluation, "FullForm"))
def do_parse(): feeder = MultiLineFeeder(code) while not feeder.empty(): parse(definitions, feeder)
def parse(self, code): return parse(definitions, MultiLineFeeder(code))
def benchmark_expression(expression_string): print(" '{0}'".format(expression_string)) expr = parse(definitions, SingleLineFeeder(expression_string)) timeit(lambda: expr.evaluate(evaluation))
def test_Span(self): self.check("a;;^b", "Power[Span[a, All], b]") feeder = MultiLineFeeder("a;;\n^b") self.compare(parse(definitions, feeder), self.parse("Span[a, All]")) self.assertRaises(InvalidSyntaxError, lambda f: parse(definitions, f), feeder)
def _evaluate(str_expression): expr = parse(definitions, SingleLineFeeder(str_expression)) return expr.evaluate(evaluation)
def contribute(self, definitions): from mathics.core.parser import parse name = self.get_name() rules = [] for pattern, function in self.get_functions(): rules.append(BuiltinRule(pattern, function, system=True)) for pattern, replace in self.rules.items(): if not isinstance(pattern, BaseExpression): pattern = pattern % {'name': name} pattern = parse(pattern) replace = replace % {'name': name} rules.append(Rule(pattern, parse(replace), system=True)) box_rules = [] if name != 'MakeBoxes': new_rules = [] for rule in rules: if rule.pattern.get_head_name() == 'MakeBoxes': box_rules.append(rule) else: new_rules.append(rule) rules = new_rules formatvalues = {'': []} for pattern, function in self.get_functions('format_'): if isinstance(pattern, tuple): forms, pattern = pattern else: forms = [''] for form in forms: if form not in formatvalues: formatvalues[form] = [] formatvalues[form].append(BuiltinRule(pattern, function, system=True)) for pattern, replace in self.formats.items(): if isinstance(pattern, tuple): forms, pattern = pattern if not isinstance(forms, tuple): forms = [forms] else: forms, pattern = [''], pattern for form in forms: if not form in formatvalues: formatvalues[form] = [] formatvalues[form].append(Rule(parse(pattern), parse(replace), system=True)) for form, formatrules in formatvalues.items(): formatrules.sort() messages = [Rule(Expression('MessageName', Symbol(name), String(msg)), String(value), system=True) for msg, value in self.messages.items()] if name == 'MakeBoxes': attributes = [] else: attributes = ['Protected'] attributes += list(self.attributes) options = {} for option, value in self.options.iteritems(): options[option] = parse(value) defaults = [] for spec, value in self.defaults.iteritems(): value = parse(value) pattern = None if spec is None: pattern = Expression('Default', Symbol(name)) elif isinstance(spec, int): pattern = Expression('Default', Symbol(name), Integer(spec)) if pattern is not None: defaults.append(Rule(pattern, value, system=True)) definition = Definition(name=name, rules=rules, formatvalues=formatvalues, messages=messages, attributes=attributes, options=options, defaultvalues=defaults) definitions.builtin[name] = definition makeboxes_def = definitions.builtin['MakeBoxes'] for rule in box_rules: makeboxes_def.add_rule(rule)
def main(): argparser = argparse.ArgumentParser( prog='mathics', usage='%(prog)s [options] [FILE]', add_help=False, description="Mathics is a general-purpose computer algebra system.", epilog="""Please feel encouraged to contribute to Mathics! Create your own fork, make the desired changes, commit, and make a pull request.""") argparser.add_argument('FILE', nargs='?', type=argparse.FileType('r'), help='execute commands from FILE') argparser.add_argument('--help', '-h', help='show this help message and exit', action='help') argparser.add_argument( '--persist', help='go to interactive shell after evaluating FILE or -e', action='store_true') argparser.add_argument('--quiet', '-q', help='don\'t print message at startup', action='store_true') argparser.add_argument('-script', help='run a mathics file in script mode', action='store_true') argparser.add_argument( '--execute', '-e', action='append', metavar='EXPR', help='evaluate EXPR before processing any input files (may be given ' 'multiple times)') argparser.add_argument('--colors', nargs='?', help='interactive shell colors') argparser.add_argument('--no-completion', help="disable tab completion", action='store_true') argparser.add_argument( '--no-readline', help="disable line editing (implies --no-completion)", action='store_true') argparser.add_argument('--version', '-v', action='version', version='%(prog)s ' + __version__) args = argparser.parse_args() quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-D' definitions = Definitions(add_builtin=True) definitions.set_line_no(0) # Reset the line number shell = TerminalShell(definitions, args.colors, want_readline=not (args.no_readline), want_completion=not (args.no_completion)) if not (args.quiet or args.script): print() print(version_string + '\n') print(license_string + '\n') print("Quit by pressing {0}\n".format(quit_command)) if args.execute: for expr in args.execute: print(shell.get_in_prompt() + expr) evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) exprs = evaluation.parse(expr) results = evaluation.evaluate(exprs, timeout=settings.TIMEOUT) shell.print_results(results) if not args.persist: return if args.FILE is not None: lines = args.FILE.readlines() if args.script and lines[0].startswith('#!'): lines[0] = '' results = [] query_gen = parse_lines(lines, shell.definitions) evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) try: for query in query_gen: results.extend( evaluation.evaluate([query], timeout=settings.TIMEOUT)) except TranslateError as exc: evaluation.recursion_depth = 0 evaluation.stopped = False evaluation.message('Syntax', exc.msg, *exc.args) except (KeyboardInterrupt): print('\nKeyboardInterrupt') except (SystemExit, EOFError): print("\n\nGood bye!\n") if not args.persist: return total_input = "" while True: try: evaluation = Evaluation(shell.definitions, out_callback=shell.out_callback) line = shell.read_line( shell.get_in_prompt(continued=total_input != '')) total_input += line try: query = parse(total_input, shell.definitions) except TranslateError as exc: if line == '' or not isinstance(exc, IncompleteSyntaxError): evaluation.message('Syntax', exc.msg, *exc.args) total_input = "" continue total_input = "" if query is None: continue results = evaluation.evaluate([query], timeout=settings.TIMEOUT) shell.print_results(results) except (KeyboardInterrupt): print('\nKeyboardInterrupt') except (SystemExit, EOFError): print("\n\nGood bye!\n") break