Using Robert Jacobson's FoxySheep parser, the command-line utility foxy-sheep
has a crude translation to Python. See https://pypi.org/project/FoxySheep/ . (And https://github.com/rljacobson/FoxySheep .)
Conversion to Python is done via transforming “InputForm” input to an “FullForm” parse tree, and then that is converted to a Python AST. Finally a Python module is used to dump the Python AST to text.
Why do we go through this more complicated process for translating one string to another?
By keeping the structure as an AST, we can contemplate more powerful transformations and make use of routines that exist for working with Python AST’s.
For example, translating {1,2,3} + 2
into Python, while not handled now, can be done by looking at the types of the operands of plus, and noticing one is a scalar while the other is a list.
Edit:
After writing this, I tried the program on the example above and found I had to extend the code to handle symbols like E
and numeric literals with a number-literal exponent.
However after doing that I was able to get this to parse:
$ foxy-sheep -o python -e '(1.*(43.013537902165325 +
43.013537902165346*E^(0.003288590604026849*t))^2)/
(3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) +
3700.328885722026*E^(0.006577181208053698*t))'
(
decimal.Decimal(1.0) * (
decimal.Decimal(43.013537902165325) +
decimal.Decimal(43.013537902165346) * math.e ** (
decimal.Decimal(0.003288590604026849) * t)) ** 2 / (
decimal.Decimal(3700.328885722024) +
decimal.Decimal(5.456968210637569) * 10 ** 12 * math.e ** (
decimal.Decimal(0.003288590604026849) * t) +
decimal.Decimal(3700.328885722026) * math.e **decimal.Decimal(0.006577181208053698) * t))
Above, we output using math.e
because the output is for Python. Had the output been either the numpy or sympy variants, constants from those modules would have been used instead.
To see a parse of this expression run:
foxy-sheep -t full -e '(1.*(43.013537902165325 + 43.013537902165346*E^(0.003288590604026849*t))^2)/ (3700.328885722024 + 5.4569682106375694*^-12*E^(0.003288590604026849*t) + 3700.328885722026*E^(0.006577181208053698*t))'
<prog:Prog> [1]
<expr:Divide> [3]
0. <expr:Parentheses> [3]
'('
1. <expr:Times> [3]
0. <expr:Number> [1]
<numberLiteral:NumberBaseTen> [1]
'1.'
1. '*'
2. <expr:Power> [3]
0. <expr:Parentheses> [3]
'('
1. <expr:PlusOp> [3]
0. <expr:Number> [1]
<numberLiteral:NumberBaseTen> [1]
'43.013537902165325'
1. '+'
2. <expr:Times> [3]
...
Lastly, I should explain that I was tempted to add a translation from Pi
to math.pi
when adding the translation of E
to math.e
. (This has since been done).
Right now what's more important is getting the overall framework right than filling out the hundreds of specifics. That said, for those who use and have a specific function that's missing, just open an github issue.
math.sin()
and all that in place ofSin[]
$\endgroup$