1

I am trying to test a Regex which should be able to split the following expressions into 3 parts:

  • test
  • true
  • false

If there are multiple iif nested, it should give me multiple matches

And I have some patterns:

iif(testExpression, trueExpression, falseExpression)

iif((@HasMinimunRegulatedCAR@==0),(([t219]>1.5) OR ([t219]<-0.5)),(([t223]>1.5) OR ([t223]<-0.5)))

iif((@HasMinimunRegulatedCAR@==1), iif((@MFIUsePAR30@==1), ([t224]>0.25), iif((@MFIUsePAR90@==1), ([t225]>0.25), (1==1))), iif((@MFIUsePAR30@==1), ([t220]>0.25), iif((@MFIUsePAR90@==1), ([t221]>0.25),(1==1))))

I am using this expression but it doesn't work when I have multiple iif nested

(^(iif\()|[^,]+)

I am running my tests using: https://regex101.com/

The expected output should be

testExpression
trueExpression
falseExpression

(@HasMinimunRegulatedCAR@==0)
([t219]>1.5) OR ([t219]<-0.5)
([t223]>1.5) OR ([t223]<-0.5)

(@HasMinimunRegulatedCAR@==1)
iif((@MFIUsePAR30@==1), ([t224]>0.25), iif((@MFIUsePAR90@==1), ([t225]>0.25), (1==1)))
iif((@MFIUsePAR30@==1), ([t220]>0.25), iif((@MFIUsePAR90@==1), ([t221]>0.25),(1==1)))
Raffaeu
  • 6,694
  • 13
  • 68
  • 110
  • 1
    could not understand clearly... for the 3 patterns that you have provided as sample... what would be the expected outputs individually ? – Mustofa Rizwan Jan 17 '18 at 08:49
  • 1
    Why don't you use a proper parser? Which language or tool do you use? What is your expected output? Are there edge cases, e.g. like `iif` being part of a string and not a keyword? Why don't you use a proper parser? – Sebastian Proske Jan 17 '18 at 08:54
  • I modified the post, language is VbScript – Raffaeu Jan 17 '18 at 08:56
  • 1
    This wan work with a recursive regex: [`iif\(((?R)+),\s*((?R)+),\s*((?R)+)\)|(?:[^,()]|\((?R)+\))`](https://regex101.com/r/QnZ7kv/1), but I doubt you can get it to work in VBScript. A .Net regex pattern can also match your conditions, but again, I don't think VBScript supports that. – Kobi Jan 17 '18 at 09:40
  • @Kobi it's ok, I can switch to C# – Raffaeu Jan 17 '18 at 10:04
  • @Kobi if I try your regular expression it works but with .NET the R for recursion doesn't exist, I need to use balancing group instead. Do you have an example of using a balancing group instead of R for recursion? – Raffaeu Jan 17 '18 at 12:51

1 Answers1

1

If .Net regular expressions are an option, you can use balancing groups to capture your iifs.

One option will capture all nested parentheses into a group called Exp:

(?>
    (?:iif)?(?<Open>\((?<Start>))   # When seeing an open parenthesis, mark
                                    # a beginning of an expression. 
                                    # Use the stack Open to count our depth.
    |
    (?<-Open>(?<Exp-Start>)\))      # Close parenthesis. Capture an expression.
    |
    [^()\n,]                        # Match any regular character
    |
    (?<Exp-Start>),(?<Start>)       # On a comma, capture an expression, 
                                    # and start a new one.
)+?
(?(Open)(?!))

Working Example, switch to the Table tab.
This option captures more than you ask for, but it does give you the full data you need to fully parse the equation.

Another option is to capture only the top-level parts:

iif\(
(?:
  (?<TopLevel>(?>
      (?<Open>\()     # Increase depth count using the Open stack.
      |
      (?<-Open>\))    # Decrease depth count.
      |
      [^()\n,]+       # Match any other boring character
      |
      (?(Open),|(?!)) # Match a comma, bun only if we're already inside parentheses.  
  )+)
  (?(Open)(?!))
  |
  ,\s*   # Match a comma between top-level expressions.
)+
\)

Working Example Here, the group $TopLevel will have three captures. For example, on your last example, it captures:

Capture 0: (@HasMinimunRegulatedCAR@==1)
Capture 1: iif((@MFIUsePAR30@==1), ([t224]>0.25), iif((@MFIUsePAR90@==1), ([t225]>0.25), (1==1)))
Capture 2: iif((@MFIUsePAR30@==1), ([t220]>0.25), iif((@MFIUsePAR90@==1), ([t221]>0.25),(1==1)))

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • 1
    I'll add some explanation a bit later, but this is a relatively standard balancing group match. – Kobi Jan 17 '18 at 13:07
  • The second example you provide does exactly what we need. Now I want to take some time to learn this because I was not aware of this capability of NET Regex – Raffaeu Jan 17 '18 at 13:12