/\G((?: [^<]+ | <(?!%) )*) (?: <%(.*?)%> | ((?=<%)) )?/gsx
Just for fun, I wanted to try to make a Perl 6 rule from this. Here it is, untested and mostly guessed. I have no idea how to do line numbers, so I cheated and imagined a method of .pos for that :)
rule code_begin ($type) {
<{
{
asp => '<%',
php => '<?',
plp => '<:'
}.{$type} // fail "Unknown type: $type"
}>
}
rule code_end ($type) {
<{
{
asp => '%>',
php => '?>',
plp => ':>'
}.{$type} // fail "Unknown type: $type"
}>
}
rule code_block ($type) {
<code_begin $type> (.*?) <code_end $type>
}
rule code_document ($type) {
[
# First, match any number of subsequent code blocks.
[
{ $?line := .pos.line }
<code_block $type> ::
{ push @?blocks, [ $?line, code => $?code_block ] }
]*
# If there is now a code_begin, obviously that is an open bloc
+k.
# (In PLP, that is valid, but let's assume for now that it's n
+ot.)
[
{ $?line := .pos.line }
<code_begin $type> \n* $?context := (\N<,15>)
{ fail "Unclosed code block on line $?line, near '$?contex
+t'" }
]?
# And then a piece of text.
# (At least one character, to avoid having empty blocks.)
[
{ $?line := .pos.line }
$?html := (.+?) [ <before <code_begin $type>> | $ ] ::
{ push @?blocks, [ $?line, html => $?html ] }
]?
]*
}
my @parsed = ($asp ~~ /<code_document 'asp'>/).{blocks}