Reputation: 938
I have been writing a regular expression that allows me to match if/elseif/else statements. I've got as far as I have (matching an if/else statement) with help from the Stack Overflow community.
This is the content I'm trying to match:
{?if gender = male}You're a guy!{?elseif gender = female}You're a gal!{?else}{#gender|capitalise}{?endif}
(The solution I'm aiming for would allow unlimited "elseif" statements, preferably.) It also needs to be able to match the following, to make sure it is backwards compatible:
{?if gender = male}Male{?else}Female{?endif}
{?if gender != female}{#gender}{?endif}
The output I'm looking for:
0: gender = male
1: You're a guy!
2: {?elseif gender = female}You're a gal!
3: {#gender|capitalise}
Number 2 should have every elseif in the same string, to allow them to be split and processed after, like:
2: {?elseif gender = female}You're a gal!{?elseif this = that}Output (...)
My current regex is close, but not good enough.
{\?if ([^{}]+)}(.+?)(?:{\?else}(.+?))?{\?endif}
I'm still learning Regular Expressions, so I'm not sure how to do this.
Upvotes: 0
Views: 1412
Reputation:
Not sure if this qualifies as an "answer", but since you're writing templates, why not use a templating language, of which there are about a thousand. Even if you needed to customize/extend them, that would be easier than writing and maintaining a bunch of spaghetti regexps.
{{#if gender = 'male'}}You're a guy!
{{elsif gender = 'female'}}You're a gal!
{{else}}{{gender|capitalise}
{{/if}}
The above is a made-up template language loosely modeled on handlebars.
If you do not find an existing templating language which meets your needs, or can be easily adapted to do so, the implementations of these engines should provide some inspiration for how to write your parser.
Upvotes: 2
Reputation: 43196
It doesn't support nested statements, but try this:
{\?if ([^{}]+)}(.*?)({\?elseif [^{}]+}.*?)*(?:{\?else}(.+?))?{\?endif}
Group 2 will capture an empty string if there are no {?elseif}
statements.
Group 3 won't exist if there's no {else}
statement.
Explanation:
{\?if // match "{?if " literally
([^{}]+)// capture the condition in group 0
}// match "}"
(.*?)// capture the content of the {if} branch in group 1
(// in group 2,...
{\?elseif //...capture "{?elseif "...
[^{}]+//...a condition...
}//..."}"...
.*?// and the content of the {elseif} branch...
)*//...as often as possible.
(?:// if possible,...
{\?else}//...match "{?else}"...
(.+?)//...and the content of the {else} branch.
)?
{\?endif}// finally, match "{?endif}".
Upvotes: 1