Question

I try to create my own markup language for displaying page templates from the database. The template can be used "conditions". They look like:

{@IF(PAYMENT_METHOD_ID==0):}
     <!-- code here -->
{@ENDIF;}

Where PAYMENT_METHOD_ID is variable .

When the page generated, we look by regular expressions "conditions" , check them and make to them proper action.

 template_html = Regex.Replace(template_html, @"{@IF\(['""]?([^'""]*?)['""]?\s*(==|!=)\s*['""]?([^'""]*?)['""]?\):}([\s\S]*?){@ENDIF;}", x =>
 {
       /* LOGIC WITH "CONDITION" */
 });

The problem occurs with nested "conditions". Ie "condition" embedded in another "condition" . For example:

{@IF(PAYMENT_METHOD_ID==0):}
     {@IF(DELIVERY_METHOD_ID==1):}
          <!-- code here -->
     {@ENDIF;}
{@ENDIF;}

In this case , the regular expression finds the first {@ENDIF}.

**{@IF(PAYMENT_METHOD_ID==0):}
     {@IF(DELIVERY_METHOD_ID==1):}
          <!-- code here -->
     {@ENDIF;}**
{@ENDIF;}

How to build a regular expression to search for only pairs of "conditions"?

Thanks!

Was it helpful?

Solution

OK, you can do this since the .NET regex engine can handle recursive matches, but it's a little complicated. I'm getting the feeling that a parser would be better suited for this scenario (you need to write one anyway)...

Regex regexObj = new Regex(
    @"{@IF\(['""]?([^'""]*?)['""]?\s* # Match IF statement, first part.
    (==|!=)                       # Match comparison operator.
    \s*['""]?([^'""]*?)['""]?\):} # Match rest of IF statement.
    (?>                           # Then either match (possessively):
     (?:                          # the following group which matches
      (?!{@IF\(|{@ENDIF;)         # only if we're not at the start of an IF/ENDIF
      .                           # any character
     )+                           # once or more
    |                             # or
     {@IF\( (?<Depth>)            # match inner IF (and increase nesting counter)
    |                             # or
     {@ENDIF; (?<-Depth>)         # match inner ENDIF (and decrease the counter).
    )*                            # Repeat as needed.
    (?(Depth)(?!))                # Assert that the nesting counter is at zero.
    {@ENDIF;}                     # Then match ENDIF.", 
    RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top