I'm writing a math app in Java that uses Javascript for scripting/input.
I want to be able to enter, say, x^2
and have Java replace that with pow(x,2)
before sending to the JavaScript parser. How can I do this type of replacement? There might be multiple different such expressions in one code snippet, which might be one or more lines.

- 802
- 11
- 26
-
1Java and JavaScript are different languages with almost nothing in common except for some syntax they both inherited from C. Do not confuse them. – cdhowie Nov 22 '14 at 05:54
-
1@cdhowie I'm not. My Java app uses a JavaScript parser (`javax.script.ScriptEngine`) for evaluating entered expressions in JavaScript. – Skylar Ittner Nov 22 '14 at 05:57
-
1I see. Well, ultimately the only bulletproof way to do this is to write a JavaScript parser that is able to recognize your extra operator. Anything less than this will have caveats where the substitution doesn't do the right thing. For example, if `x^2` appears in a string literal, you don't want to replace it. – cdhowie Nov 22 '14 at 05:59
-
3You need to take associativity and precedence into account - therefore you need to write a parser. – Ed Heal Nov 22 '14 at 06:00
-
if you mandate parens around replaced subsets, you _might_ be able to get away with naive substitution, we would need to know more about the input possibilities. if not a parser is a sure fire, if complicated, way to solve the problem. – dandavis Nov 22 '14 at 06:05
-
2I'm not sure what this app is for, but if there's any decent chance that you'll have to handle more complex expressions including parenthesized ones, I wouldn't start down the regex path, except perhaps if you need a simple prototype for a demo. You'll probably ending up just making the regex more and more complicated and then having to throw the whole thing out anyway. – ajb Nov 22 '14 at 06:09
-
2You *cannot* reliably do this with regex. It is simply not powerful enough. You need a real math parser. See: [Evaluating a math expression given in string form](https://stackoverflow.com/questions/3422673/evaluating-a-math-expression-given-in-string-form). – Boann Nov 22 '14 at 10:32
3 Answers
You should fork the esprima JS parser to add the ^
operator with appropriate precedence etc. Then walk the parse tree, identify where it is used, and do the lexical substitution. This link might be useful: http://ariya.ofilabs.com/2011/08/math-evaluator-in-javascript-part-2.html. Not quite sure how you'll call this from your Java program, but I'm sure you can figure that out.
Or, the parser in http://mathjs.org/ apparently already supports ^
, so you could use that. Or, there is http://silentmatt.com/javascript-expression-evaluator/ which also appears to support ^
. Or http://jsep.from.so/, "a tiny JavaScript expression parser".
Related SO question: Safe evaluation of arithmetic expressions in Javascript

- 1
- 1
UPDATE:
I'm not sure how much complexity you're expecting, but if you want it to be able to handle some tricky expression, you might as well use parser library.
Supposing you're talking about javascript and you're replacing string input, do the following.
"x^2".replace(/(.*)\^(\d+)/, "pow($1, $2)")

- 2,003
- 4
- 27
- 42
-
i would add more context to your RegExp to handle spaces, negatives, etc. – dandavis Nov 22 '14 at 05:59
-
1
-
3What if the user enters more complicated things, like `x^0.5` or `(x+y)^(z-4)`? (Or even `x^y^2`.) – nnnnnn Nov 22 '14 at 06:00
-
-
nothings perfect, but the answer can be made better with some extra attention, and might be satisfactory depending on usage. it's going to be a WHOLE lot more complicated if RegExp fails to pan out. – dandavis Nov 22 '14 at 06:02
-
@dandavis Expression strings **are** complicated. Regexes are nice but they cannot solve every problem. Regexes do not deal well with things like nested parentheses. – ajb Nov 22 '14 at 06:05
-
@ajb: it depends on use, but a multi-pass, multi-rx workload can handle many nested situations with atomic operations. i completely agree RXs is not a silver bullet, but if all that needs done is 1 or more operations like OP described, it doesn't sound to me like it's categorically beyond the pay grade of an RX. I knew some unix scripters would could seemingly move mountains with an RX. – dandavis Nov 22 '14 at 06:10
-
@dandavis RX cannot parse regular languages. You can hack it by applying a regex multiple times, but there will always be some edge case where it fails to do the right thing -- operator precedence and associativity being a huge example of this. If you do manage to get it right with a regex that can be applied multiple times, then you'll have created such an unmantainable monster that it would have been better just to write a JS parser anyway. – cdhowie Nov 22 '14 at 06:14
-
1@dandavis yeah, and I'll bet their regexes were about as readable as Egyptian hieroglyphics... :) :) :) – ajb Nov 22 '14 at 06:14
-
1@dandavis tl;dr version is that "can" and "should" are different things. Can you do this with regex? Maybe, but unlikely. Should you. No. Hell, no. – cdhowie Nov 22 '14 at 06:15
-
@cdhowie: i just worry that a custom parser could be a bridge too far and that a few hours of debugging RegExp might be enough for this situation, but neither of us know enough to make that call. there's such a thing as over-building, even in a world of mostly under-built crap... but i 100% agree parser is a more professional and expandable option. it just might be as likely to force project abandonment as work... – dandavis Nov 22 '14 at 06:17
-
@dandavis The amount of work to do this right in regex is incredible. I say this as someone with extensive experience both with regex and hand-writing recursive descent parsers. The parser will be easier to write, easier to get correct, easier to debug, and easier to extend later if OP wants to add other operators. I can virtually guarantee that if you spent less time on a regex than you did on a parser that it would be extremely easy to find a case where the regex fails to do the right thing. – cdhowie Nov 22 '14 at 06:19
-
i have updated my ans. it may works many cases but not all cases. you may try this. – Ahosan Karim Asik Nov 22 '14 at 06:55
try this: update: it is possible some cases
var re = /(?![\+\-\*\/\(\)\^\s])([a-zA-Z0-9]+)\^([a-zA-Z0-9]+)/gm;
var str = 'w*x^2 +5^9';
var subst = 'pow($1,$2)';
var result = str.replace(re, subst);
And better reference for math calculation.http://mathjs.org/
example & output
// expressions
math.eval('1.2 * (2 + 4.5)'); // 7.8
math.eval('5.08 cm to inch'); // 2 inch
math.eval('sin(45 deg) ^ 2'); // 0.5
math.eval('9 / 3 + 2i'); // 3 + 2i
math.eval('det([-1, 2; 3, 1])'); // -7

- 3,219
- 1
- 18
- 27
-
1What if the input is `y^3 + x^2`? The question said "There might be multiple different such expressions in one code snippet". – nnnnnn Nov 22 '14 at 06:03
-
-
What about `a^(b^c)` or `(a^b)^c`? Good luck making those substitutions correctly with just regex. – cdhowie Nov 22 '14 at 06:07
-
@AhosanKarimAsik Hint: You can't. Regex doesn't do recursion like that; it cannot parse regular languages. – cdhowie Nov 22 '14 at 06:11
-
@cdhowie Note that I'm using Java for the replacement, so if recursion can't be done with a Regex, maybe a recursive function with Regex could work. – Skylar Ittner Nov 22 '14 at 06:17
-
i think, for math calculation, use mathjs is better and ref: [http://mathjs.org/](http://mathjs.org/) – Ahosan Karim Asik Nov 22 '14 at 06:18
-
@SkylarMT Very unlikely. Bear in mind that as I said earlier, you have to take into account that you might be in the middle of a string literal for example. Detecting this kind of situation in regex is very hard. It would be easier to write a correct parser than a correct regex. – cdhowie Nov 22 '14 at 06:23
-
forking the old jsmin routine lets you easily avoid string literals without the complications of a full parser... – dandavis Nov 22 '14 at 06:25
-
2@AhosanKarimAsik Repeat very slowly after me: **YOU CANNOT PARSE EXPRESSIONS WITH REGEXP**. For every case you come up with that works, I can easily come up with a counter-example that doesn't work. This is parsing theory 101. – Nov 22 '14 at 06:59
-
i think, it is not possible to use only regex. it may possible to use any function with regex. but i can't more try.. – Ahosan Karim Asik Nov 22 '14 at 07:04