alexbirkett
alexbirkett

Reputation: 2682

Reluctant quatnifier not working in Javascript

If the following function is called in node v0.10.26:

    function parseAndLog(constraint) {
        var constraintRegex = /\s*(.*?)\s*(<=|==|>=|[GL]?EQ)\s*(.*?)\s*(!required|!strong|!medium|!weak)?/;
        console.log(constraintRegex.exec(constraint));
    }

with the input:

"thumb.top == group.top + 20"

I expected that the following would be returned as substring matches (as happens when a similar function is called in Java)

thumb.top 
==
group.top + 20

But only the following is returned

thumb.top 
==

I hoped that "group.intrinsicHeight == preamble.bottom !medium" would yeild

group.intrinsicHeight
==
preamble.bottom
!medium

but only get the following

group.intrinsicHeight
==

I suspect the issue is something to do with the (.*?) group. I think this is known as a reluctant quantifier. Is it even supported by Javascript? If not, is there a workaround? Any help greatly appreciated.

Upvotes: 0

Views: 90

Answers (2)

Avinash Raj
Avinash Raj

Reputation: 174816

I suggest you to use start and end anchors.

^\s*(.*?)\s*(<=|==|>=|[GL]?EQ)\s*(.*?)\s*(!required|!strong|!medium|!weak)?$

DEMO

String str = "thumb.top == group.top + 20\n" + 
             "group.intrinsicHeight == preamble.bottom !medium";
Matcher m = Pattern.compile("(?m)^\\s*(.*?)\\s*(<=|==|>=|[GL]?EQ)\\s*(.*?)\\s*(!required|!strong|!medium|!weak)?$").matcher(str);
while(m.find())
{
    if(m.group(1) != null)  { System.out.println(m.group(1)); }
    if(m.group(1) != null)  { System.out.println(m.group(2)); }
    if(m.group(1) != null)  { System.out.println(m.group(3));  }
    if(m.group(1) != null)  { System.out.println(m.group(4)); }
}

Because you described all the patterns except (<=|==|>=|[GL]?EQ) to repeat zero or more times. So it don't care about that there is a following (!required|!strong|!medium|!weak) or not, since you made this pattern as optional. By adding the start and end anchors, it ensures that the optional (!required|!strong|!medium|!weak) is followed by end of the line anchor. So regex engine tries to match upto the line end.

Upvotes: 1

alexbirkett
alexbirkett

Reputation: 2682

Adding start and end anchors made the regular expression behave as desired in Javascript

e.g. /^\s*(.*?)\s*(<=|==|>=|[GL]?EQ)\s*(.*?)\s*(!(required|strong|medium|weak))?$/;

Thanks to @avinash-raj for the suggestion.

If anybody could offer an explanation as to why this works and if the (.*?)group is in fact a "reluctant quantifier", I'd be grateful.

Upvotes: 1

Related Questions