UNPKG

5.11 kBJavaScriptView Raw
1'use strict';
2
3var extend = require('../utils/object').extend;
4var customs = require('../utils/customs');
5
6function factory(type, config, load, typed, math) {
7 var _parse = load(require('./parse'));
8
9 /**
10 * @constructor Parser
11 * Parser contains methods to evaluate or parse expressions, and has a number
12 * of convenience methods to get, set, and remove variables from memory. Parser
13 * keeps a scope containing variables in memory, which is used for all
14 * evaluations.
15 *
16 * Methods:
17 * const result = parser.eval(expr) // evaluate an expression
18 * const value = parser.get(name) // retrieve a variable from the parser
19 * const values = parser.getAll() // retrieve all defined variables
20 * parser.set(name, value) // set a variable in the parser
21 * parser.remove(name) // clear a variable from the
22 * // parsers scope
23 * parser.clear() // clear the parsers scope
24 *
25 * Example usage:
26 * const parser = new Parser()
27 * // Note: there is a convenience method which can be used instead:
28 * // const parser = new math.parser()
29 *
30 * // evaluate expressions
31 * parser.eval('sqrt(3^2 + 4^2)') // 5
32 * parser.eval('sqrt(-4)') // 2i
33 * parser.eval('2 inch in cm') // 5.08 cm
34 * parser.eval('cos(45 deg)') // 0.7071067811865476
35 *
36 * // define variables and functions
37 * parser.eval('x = 7 / 2') // 3.5
38 * parser.eval('x + 3') // 6.5
39 * parser.eval('function f(x, y) = x^y') // f(x, y)
40 * parser.eval('f(2, 3)') // 8
41 *
42 * // get and set variables and functions
43 * const x = parser.get('x') // 7
44 * const f = parser.get('f') // function
45 * const g = f(3, 2) // 9
46 * parser.set('h', 500)
47 * const i = parser.eval('h / 2') // 250
48 * parser.set('hello', function (name) {
49 * return 'hello, ' + name + '!'
50 * })
51 * parser.eval('hello("user")') // "hello, user!"
52 *
53 * // clear defined functions and variables
54 * parser.clear()
55 *
56 */
57 function Parser() {
58 if (!(this instanceof Parser)) {
59 throw new SyntaxError('Constructor must be called with the new operator');
60 }
61 this.scope = {};
62 }
63
64 /**
65 * Attach type information
66 */
67 Parser.prototype.type = 'Parser';
68 Parser.prototype.isParser = true;
69
70 /**
71 * Parse an expression and return the parsed function node.
72 * The node tree can be compiled via `code = node.compile(math)`,
73 * and the compiled code can be executed as `code.eval([scope])`
74 * @param {string} expr
75 * @return {Node} node
76 * @throws {Error}
77 */
78 Parser.prototype.parse = function (expr) {
79 throw new Error('Parser.parse is deprecated. Use math.parse instead.');
80 };
81
82 /**
83 * Parse and compile an expression, return the compiled javascript code.
84 * The node can be evaluated via code.eval([scope])
85 * @param {string} expr
86 * @return {{eval: function}} code
87 * @throws {Error}
88 */
89 Parser.prototype.compile = function (expr) {
90 throw new Error('Parser.compile is deprecated. Use math.compile instead.');
91 };
92
93 /**
94 * Parse and evaluate the given expression
95 * @param {string} expr A string containing an expression, for example "2+3"
96 * @return {*} result The result, or undefined when the expression was empty
97 * @throws {Error}
98 */
99 Parser.prototype.eval = function (expr) {
100 // TODO: validate arguments
101 return _parse(expr).compile().eval(this.scope);
102 };
103
104 /**
105 * Get a variable (a function or variable) by name from the parsers scope.
106 * Returns undefined when not found
107 * @param {string} name
108 * @return {* | undefined} value
109 */
110 Parser.prototype.get = function (name) {
111 // TODO: validate arguments
112 return name in this.scope ? customs.getSafeProperty(this.scope, name) : undefined;
113 };
114
115 /**
116 * Get a map with all defined variables
117 * @return {Object} values
118 */
119 Parser.prototype.getAll = function () {
120 return extend({}, this.scope);
121 };
122
123 /**
124 * Set a symbol (a function or variable) by name from the parsers scope.
125 * @param {string} name
126 * @param {* | undefined} value
127 */
128 Parser.prototype.set = function (name, value) {
129 // TODO: validate arguments
130 return customs.setSafeProperty(this.scope, name, value);
131 };
132
133 /**
134 * Remove a variable from the parsers scope
135 * @param {string} name
136 */
137 Parser.prototype.remove = function (name) {
138 // TODO: validate arguments
139 delete this.scope[name];
140 };
141
142 /**
143 * Clear the scope with variables and functions
144 */
145 Parser.prototype.clear = function () {
146 for (var name in this.scope) {
147 if (this.scope.hasOwnProperty(name)) {
148 delete this.scope[name];
149 }
150 }
151 };
152
153 return Parser;
154}
155
156exports.name = 'Parser';
157exports.path = 'expression';
158exports.factory = factory;
159exports.math = true; // requires the math namespace as 5th argument
\No newline at end of file