Expression Compiler
Compile math expressions to a useful AST, with built-in compilers to turn the AST into a sanitized javascript function.
Install
$ npm install expression-compiler
Usage
Safely execute arbitrary math expression
and also get the raw js generated for the function
> var mkFunc = require('expression-compiler/func');undefined> var expressionFunc = compile('c*sin(2*t)+1');undefined> expressionFunc({c: 0.5});0.9999999999999999> mkFunc.express('sqrt(x^2 + y^2)')'(Math.sqrt((Math.pow(symbols["x"],2.0)+Math.pow(symbols["y"],2.0))))'
Note that everything in the global Math
is made available by the built-in function compiler, and it is assumed that the global Math
assumed available by its express
function.
Get an Abstract Syntax Tree from a math expression
and then echo back the original expression with just the AST
> var parse = require('expression-compiler/parse');undefind> var ast = parse('sin(t)^2 + cos(t)^2');unefined> ast{ id: 0, type: 'ASTNode', node: 'expr', template: '#', children: [ { id: 1, type: 'ASTNode', node: 'func', template: '# +#', children: [Object], options: [Object] } ], options: {} }> console.log(JSON.stringify(ast, null, 2)); // print out the whole thing{ "id": 0, "type": "ASTNode", "node": "expr", "template": "#", "children": [ { "id": 1, "type": "ASTNode", "node": "func", "template": "# +#", "children": [ { "id": 2, "type": "ASTNode", "node": "func", "template": "#^#", "children": [ { "id": 3, "type": "ASTNode", "node": "func", "template": "sin(#)", "children": [ { "id": 4, "type": "ASTNode", "node": "name", "template": "t", "children": [], "options": { "key": "t" } } ], "options": { "key": "sin" } }, { "id": 5, "type": "ASTNode", "node": "literal", "template": "2", "children": [], "options": { "value": 2 } } ], "options": { "key": "pow" } }, { "id": 6, "type": "ASTNode", "node": "func", "template": "#^#", "children": [ { "id": 7, "type": "ASTNode", "node": "func", "template": " cos(#)", "children": [ { "id": 8, "type": "ASTNode", "node": "name", "template": "t", "children": [], "options": { "key": "t" } } ], "options": { "key": "cos" } }, { "id": 9, "type": "ASTNode", "node": "literal", "template": "2", "children": [], "options": { "value": 2 } } ], "options": { "key": "pow" } } ], "options": { "key": "sum" } } ], "options": {}}undefined> var echoer = require('expression-compiler/echo');undefined> echoer.fromAST(ast);'sin(t)^2 + cos(t)^2'
Parsing
New AST node design:
id: 0 type: 'ASTNode' node: 'expr' template: '#' children: options: {}
id
must be uniquetype
must be a valid node typeoptions
contains different properties depending on the node type
AST Node Types
expr
options:
{}
func
options:
key: 'funcName'
Infix functions should be normal function nodes. Here are some examples for +
with 2 or 3 operands:
id: 0 type: 'ASTNode' node: 'func' template: '# + # + #' children: someNode anotherNode andAnother options: key: 'sum'
Normal functions can take multiple arguments
id: 0 type: 'ASTNode' node: 'func' template: 'min(#, #)' children: someNode anotherNode options: key: 'min'
name
options:
key: 'varName'
literal
options:
value: 1