This is more of a lexer/parser design question:
Imagine having to lex/parse legacy templates (for static code analysis purposes) which are similar to html but with two additional features:
- custom tags which have a certain prefix. '<xy...' for example
- regions that contain a language expression delimited by a specific character. '#' for example. Regions execute code and render text or nothing as a result.
These kind of templates are processed by an appserver to produce webpages. Now, if i take the XMLLexer / XMLParser examples from the website as a base grammar, consider following rules:
- custom tags are allowed everywhere in the html "sea". See below for some creative examples.
- expression regions are also allowed everywhere in the html "sea", but only as attribute values inside of custom tags. See below for examples.
With these two basic rules in mind and using the XMLLexer as a base: i would add two additional lexer modes for both rules and configure them so that i can jump from mode to mode as needed.
Now here is the question: how would i define the "jumping" part?
The everywhere part seems hard to to, because i have to consider every parser rule and include the possibility of the expression region or a custom tag to start. I can't get my head around this. Is it possible to have a kind of 'global' rule that triggers no matter where you are in the lexing/parsing process? Are lexer modes even the right tool for this use case?
Code Examples:
Note: not all examples are useful or best practice but they are certainly possible and present in legacy code:
Examples of expression regions:
<#test# asdf="fff">ggg</#test#>
<te#st# asdf="fff">ggg</te#st#>
<t#es#t asdf="fff">ggg</t#es#t>
<#te#st asdf="fff">ggg</#te#st>
<test #asdf#="fff">ggg</test>
<test asdf="#fff#">ggg</test>
<test asdf="fff">#ggg#</test>
Use of custom tags:
<xyif condition="#yesorno#">
Si
<xyelse>
No
</xyif>
<div conditionalvalue="
<xyif condition="#yesorno#">
Si
<xyelse>
No
</xyif>
"/>
<div
<xyif condition="#conditionalattribute#">
attributable="attributable"
</xyif>
/>
<xyif condition="#showelement#">
<div class="conditionalelement">I am conditional</div>
</xyif>
<xyif condition="#outerbox#">
<div class="conditional_outerbox">
</xyif>
<div class="innercontent">
...
</div>
<xyif condition="#outerbox#">
</div>
</xyif>