1from re import match
2
3from ..core import sympify
4
5
6def mathematica(s):
7    return sympify(parse(s))
8
9
10def parse(s):
11    s = s.strip()
12
13    # Begin rules
14    rules = (
15        # Arithmetic operation between a constant and a function
16        (r'\A(\d+)([*/+-^])(\w+\[[^\]]+[^\[]*\])\Z',
17         lambda m: m.group(
18             1) + translateFunction(m.group(2)) + parse(m.group(3))),
19
20        # Arithmetic operation between two functions
21        (r'\A(\w+\[[^\]]+[^\[]*\])([*/+-^])(\w+\[[^\]]+[^\[]*\])\Z',
22         lambda m: parse(m.group(1)) + translateFunction(
23             m.group(2)) + parse(m.group(3))),
24
25        (r'\A(\w+)\[([^\]]+[^\[]*)\]\Z',  # Function call
26         lambda m: translateFunction(
27             m.group(1)) + '(' + parse(m.group(2)) + ')'),
28
29        (r'\((.+)\)\((.+)\)',  # Parenthesized implied multiplication
30         lambda m: '(' + parse(m.group(1)) + ')*(' + parse(m.group(2)) + ')'),
31
32        (r'\A\((.+)\)\Z',  # Parenthesized expression
33         lambda m: '(' + parse(m.group(1)) + ')'),
34
35        (r'\A(.*[\w\.])\((.+)\)\Z',  # Implied multiplication - a(b)
36         lambda m: parse(m.group(1)) + '*(' + parse(m.group(2)) + ')'),
37
38        (r'\A\((.+)\)([\w\.].*)\Z',  # Implied multiplication - (a)b
39         lambda m: '(' + parse(m.group(1)) + ')*' + parse(m.group(2))),
40
41        (r'\A(-? *[\d\.]+)([a-zA-Z].*)\Z',  # Implied multiplication - 2a
42         lambda m: parse(m.group(1)) + '*' + parse(m.group(2))),
43
44        (r'\A([^=]+)([\^\-\*/\+=]=?)(.+)\Z',  # Infix operator
45         lambda m: parse(m.group(1)) + translateOperator(m.group(2)) + parse(m.group(3))))
46    # End rules
47
48    for rule, action in rules:
49        m = match(rule, s)
50        if m:
51            return action(m)
52
53    return s
54
55
56def translateFunction(s):
57    if s.startswith('Arc'):
58        return 'a' + s[3:]
59    return s.lower()
60
61
62def translateOperator(s):
63    dictionary = {'^': '**'}
64    if s in dictionary:
65        return dictionary[s]
66    return s
67