0

I have a problem with a javascript regexp. This is my regex:

(([\+\-\/\*\^]?)([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*)?(([(]*([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?)[)]*))?([\+\-\/\*\^])([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*))+

This regexp test if the text is an matematical formula (18*19)/2 for example, and I can add QXX like a variable, for example: Q18/42+7*Q7

This regexp work perfectly in java (I have tested it on http://fiddle.re/dnbh6). But, when I tried to convert it in javascript, it doesnt work... This is all solutions that I tried:

var reg =/(([\+\-\/\*\^]?)([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*)?(([(]*([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?)[)]*))?([\+\-\/\*\^])([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*))+/g;
reg.test("Q18+aaaa)//return true, but in java this is resturn false

var reg= new RegExp("(([\+\-\/\*\^]?)([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*)?(([(]*([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?)[)]*))?([\+\-\/\*\^])([(]*(([(]?((([+-]?\d+([.,]?(\d+)?)?)|(Q[0-9]+)?)([e][+-]\d+)?)[)]?)|([(]?value[)]?))[)]*))+", "g");
reg.test("Q18+aaaa)//return true, but in java this is resturn false

So, if you had any idea, i will try it.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • http://regexpal.com/ is a nice tool to test regex expressions – Augusto Hack Apr 29 '13 at 13:27
  • keep in mind that `[(]?...[)]?` does not guarantee that all parenthesis are paired, you can open without closing and vice-versa, you need a PCRE's `(?R)` equivalent, [related SO question](http://stackoverflow.com/questions/4414339/recursive-matching-with-regular-expressions-in-javascript) – Augusto Hack Apr 29 '13 at 13:42
  • I hope that you generated the regex, rather than it being one long string in your program... I analyze it half way and give up, but it seems that you are using too many capturing groups. – nhahtdh Apr 29 '13 at 13:44
  • To add to what hack.augusto said, neither Java nor JavaScript support recursive regex. – nhahtdh Apr 29 '13 at 13:44

2 Answers2

0

I am not sure if that is correct what you are doing here, but I assume I know, what your problem is.

In Java if you are using the matches() method, it matches the regex against the complete string.

Javascript isn't doing that, it returns also partial matches. To achieve the same behaviour you have to add anchors around your regex. ^ to match the start of the string and $ to match the end of the string.

So it should look something like this (shortened the giant regex!):

var reg= new RegExp("^(([\+\-\/\*\^]?)...([(]?value[)]?))[)]*))+$", "g");
  Added anchors ==>  ^                                          ^
stema
  • 90,351
  • 20
  • 107
  • 135
0

From the number of parenthesis that you have on this regex, I'm assuming you don't want to capture any data. A better regex to just validate the input might look like:

/
   [(](?R)[)] # match parenthesis
   |(?R)[-+/*^](?R) # allow to use one operator over to operands
   # a number, can be separated by "," or "." and can be followed by a exponent,
   # do _not_ accept decimal mark
   |[+-]?\d+([,.]\d+)?(e[+-]\d+)?
   |Q[0-9]+(e[+-]\d+)?
   |value
/x

Because of the recursion you can't use anchors, also, I used PCRE's (?R) you will need some sort of library support to do recursion, as said in the comments.

Edit: If you want to save the data you can write a parsing function, something with the following outline:

function parse(input) {
    var output = [],
        brackets = 0,
        op = null,
        qvariable = false,
        buff = [],
        stringbuff = '',
        sign = null;

    for (i = 0; i < input.length; i++) {
        var currentChar = input.charAt(i);

        if (sign && /[0-9]/.test(currentChar)) {
            return 'erro, expecting number';
        }

        if (op != null && /[-+/*(]/.test(currentChar)) {
            op = null;
        }

        switch (currentChar) {
            case '(':
                buff.push(output);
                output = [];
                break;

            case ')':
                if (op != null) { return 'operator before parenthesis close'; }
                output.push(stringbuff);
                parenthesis = output
                output = buff.pop();
                output.push(parenthesis);

                stringbuff = '';
                break;

            case '-':
            case '+':
            case '/':
            case '*':
                if (op == null) {
                    op = currentChar;
                } else {
                    if (currentChar == '-' && currentChar == '+') {
                        sign = currentChar;
                    } else {
                        return 'error, two operators in sequence';
                    }
                }
                output.push(stringbuff);
                output.push(op);
                stringbuff = '';
                break;

            case 'Q':
                if (!stringbuff.length) { return null; }
                qvariable = true;
                stringbuff += currentChar;

            // todo: handle comma, dot and exponents
            default:
                if (/[0-9]/.test(currentChar)) {
                    if (sign) { 
                        stringbuff += sign;
                        sign = null;
                    }
                    stringbuff += currentChar;
                } else {
                    return 'unexpected input';
                }
                break;
        }
    }
    if (stringbuff.length) {
        output.push(stringbuff);
    }
    return output;
}
Augusto Hack
  • 2,032
  • 18
  • 35