7

I would like to find a javascript parser that can handle and evaluate simple expressions. The parser should be able to evaluate the regular mathematical expressions, and support custom functions with parameters. It also has to support strings handling. String concatenation with || operator support is preferred, but it is okay if + will do the trick.

Examples of an expression that should be handled by the parser:

3 * (2 + 1) - 1

2 * func(2, 2)

func('hello world', 0, 5) || ' you'

Has anyone implemented such a thing or where can I find something similar?

Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
  • are you looking for a javascript parser to run in a different language? like a c++ implementation of a javascript parser? Or something in javascript for javascript? – Jonathan Fingland Jun 27 '09 at 09:52
  • Sorry if I was not clear about this. No, I mean a parser written in javascript that parse and evaluate simple expression as described above. –  Jun 27 '09 at 10:56
  • is the set of "custom" functions known? – Jonathan Fingland Jun 27 '09 at 11:05
  • Exactly. The idea is you first register your own functions with their names in the parsing class, then you can use them in expressions. –  Jun 27 '09 at 11:58

7 Answers7

9

I have a modified version of an ActionScript parser (written in AS, not parses AS) that supports custom functions, but not strings. It would probably be easy to add string support though. I'll upload it somewhere so you can get it at http://silentmatt.com/parser2.js http://silentmatt.com/parser3.js.

Edit: I added basic support for strings pretty easily. It doesn't support escape sequences and toJSFunction doesn't work, but it only took a few minutes to get it working. Changing the concatenation operator to "||" should be pretty easy too.

Here's how you would evaluate your example expressions:

js> var parser = new Parser();
js> parser.parse("3 * (2 + 1) - 1").evaluate();
8
js> parser.parse("2 * func(2; 2)").evaluate({ func:Math.pow });
8
js> function substr(s, start, end) { return s.substring(start, end); }
js> parser.parse("func('hello world'; 0; 5) + ' you'").evaluate({ func:substr });
hello you

I don't remember why I used semicolons as argument separators; I think it has something to do with differentiating between functions and built-in "operator" functions.

Another edit:

I've been playing with this a little, and now there's a version with better string support at http://silentmatt.com/parser3.js (toJSFunction works, and you can use standard JavaScript escape sequences). It also uses commas to separate arguments for all functions and || as the string concatenation operator instead of +, which only does addition.

Matthew Crumley
  • 101,441
  • 24
  • 103
  • 129
  • Thank you man. I really appreciate your help. This one matches what I described and it is also easy to modify and extend. This is what I was looking for. I am really thankful for this. –  Jun 28 '09 at 01:15
  • Another comment... Matthew, did I forgot to say that you are great! I really appreciate the modification in the third version man. keep up the good work. All the best. –  Jun 28 '09 at 01:25
  • No problem. I'd been meaning to play with this for awhile (I haven't touched it for several months). A lot of the credit goes to Raphael Graf, who wrote the original version though. – Matthew Crumley Jun 28 '09 at 01:43
  • This parser is really awesome. Can you specify what license it is released under? I can not find a reference to the original parser which it is based off of. – Ryan Hoffman Jan 11 '12 at 15:50
  • @RyanHoffman Hmm, apparently the original ActionScript version isn't online anymore. His code just had a note saying to give credit to the author. I don't care what people do with it, just keep the comment at the top. – Matthew Crumley Jan 12 '12 at 13:52
4

Try math.js:

http://mathjs.org

Comes with an extensive and easy to use parser, which also supports assignment and usage of variables and functions like in your example expression. Integrates seamlessly with "native" JavaScript: you can get and set variables and functions from the Parsers scope.

Your example code would be evaluated as:

var parser = math.parser();
parser.set('func', function () {
    // ... do something ...
});
parser.evaluate('3 * (2 + 1) - 1');
parser.evaluate('2 * func(2, 2)');
parser.evaluate('func("hello world", 0, 5) + " you"');

Functions can also be defined in the parser itself (currently only single-line functions):

parser.evaluate('function f(x, y) = x ^ y');
parser.evaluate('f(2, 3)'); // 8
atulmy
  • 1,364
  • 15
  • 23
Jos de Jong
  • 6,602
  • 3
  • 38
  • 58
3

haven't used it, but a quick google reveals http://jsfromhell.com/classes/math-parser

edit:

What you want to do may be out of reach of the first link, you could also have a look at Douglas Crockford's "parser for Simplified JavaScript"

It's just a parser, so you would have to do all the evaluation yourself. It would, however, make it somewhat easier and it doesn't use eval.

cobbal
  • 69,903
  • 20
  • 143
  • 156
  • Thank you. This one sounds promising and the closest match to my request, however, it lacks strings support. Also modifying it to support strings is difficult, since it does not relay on recursive approach rather than an optimized (but nice) way of parsing. Can anyone help modifying it to support strings? –  Jun 27 '09 at 11:02
2

Assuming you mean a javascript parser in javascript, you probably want eval()

see: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Functions/Eval

Just note that eval, if used improperly, can represent a security risk.

Jonathan Fingland
  • 56,385
  • 11
  • 85
  • 79
  • No, eval is not a choice for me. As you said, it will introduce security risks, and in my case the risk is really high. I want a custom and limited parser to do what is described above. But Thanks –  Jun 27 '09 at 10:59
0

See this tutorial for how to build arbitrary parsers/compilers. (Basically it automates the construction of recursive descent parsers from grammars, meaning you can change your expression syntax easily). The whole tutorial is done in JavaScript, so it applies directly to you.

http://www.bayfronttechnologies.com/mc_tutorial.html

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
0

Narcissus implements a proper JS parser in JS: http://mxr.mozilla.org/mozilla/source/js/narcissus/jsparse.js. Written by Brendan Eich (the JS creator) too!

Nickolay
  • 31,095
  • 13
  • 107
  • 185
0

Try js-expression-eval

It is javascript based string expression evaluation library.

This library can evaluate a string expression and return the result. It supports basic arithmetic operations and it also supports custom variables and functions.

Example:

const parser = new ExpressionParser('A.B + A.C' ,
 { 
    A: (identifier) => {
    switch (identifier) {
        case 'B':
            return 2;
        case 'C':
            return 3;
        }
    }
});
const result = parser.evaluate();
console.log(result); // 5
Praveen N
  • 137
  • 1
  • 7