simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

Parser.js (4487B)


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