[TxMt] How to match recursive blocks when begin goes over two lines

Andreas Pardeike andreas at pardeike.net
Fri Sep 15 13:26:50 UTC 2006


Hi,

I am slowly adapting to the language defs. Great.

Now, I am having difficulties to specify recursive blocks for a  
language.
So far, I got it working pretty good for things like

-----------------
%function foo() {
   %{
   %}
%}
-----------------

as I created a matcher for {%..%} that calls itself and thus the matcher
for the function which for simplicity I state here as

begin = '%function .*\(\) \{'
end   = '%}'

will match the last %} and not the previous one. Cool.

Now, how do I allow for this case:

---------------
%function foo()
{
   %{
   %}
%}
---------------

I can't get it to work even though I know that the matcher only  
matches whole
lines. The language I try to define is an obsolete old IBM mainframe  
macro
language called Net.DATA (please, don't ask why).

So a block starts either as '%keyword_and_more {' or as '% 
keyword_and_more\n{'
and always ends in '%}'.

Is it possible to define this? I assume that I need to define two  
rule sets to
simulate the two states and then either start in state A or B and do the
recursion within each set. Right?

Andreas Pardeike


PS: If you like, you can see my current definition:

{	scopeName = 'source.netdata';
	fileTypes = ( '' );
	foldingStartMarker = '%.*\{|%(?i:if)';
	foldingStopMarker = '%\}|%(?i:endif)';
	patterns = (
		{	include = '#embeddedstuff'; },
		{	name = 'source.netdata.comment';
			match = '^%\{.*?%\}';
		},
	);
	repository =
	{	embeddedstuff = { patterns = (
				{	include = '#shtml'; },
				{	include = '#netdata'; },
			);
		};
		netdata = { patterns = (
				{	name = 'keyword.control.netdata.conditional';
					match = '%(?i:if|else|endif)';
				},
				{	name = 'keyword.control.netdata.include';
					match = '%(?i:include).*';
				},
				{	name = 'keyword.control.shtml.include';
					match = '<!--#%(?i:include).*-->';
				},
				{	name = 'source.netdata.block';
					begin = '(%\{(?i:macro)?)';
					end = '(%\})';
					captures = { 1 = { name = 'keyword.control.netdata'; }; };
					patterns = ( { include = '#embeddedstuff'; } );
				},
				{	name = 'source.netdata.function';
					begin = '(%function\s*\(([^)]*)\))\s+(\w+\(.*\))\s*(\{)';
					end = '(%\})';
					captures =
					{	1 = { name = 'keyword.control.netdata'; };
						2 = { name = 'source.netdata.function.type'; };
						3 = { name = 'source.netdata.function.name'; };
					};
					patterns = ( { include = '#embeddedstuff'; } );
				},
				{	name = 'source.netdata.block';
					begin = '(%.*?)\s*\(.*\)\s*(\{)';
					end = '(%\})';
					captures =
					{	1 = { name = 'keyword.control.netdata'; };
						2 = { name = 'keyword.control.netdata'; };
					};
					patterns = ( { include = '#embeddedstuff'; } );
				},
				{	name = 'source.netdata.block';
					begin = '(%.*)\s?(\{)';
					end = '(%\})';
					captures =
					{	1 = { name = 'keyword.control.netdata'; };
						2 = { name = 'keyword.control.netdata'; };
					};
					patterns = ( { include = '#embeddedstuff'; } );
				},
			);
		};
		shtml =
		{	name = 'source.netdata.embedded.shtml';
			begin = '(?=<!--#)';
			end = '-->';
			patterns = (
				{	name = 'keyword.control.shtml.include';
					match = '(?i:include.*?=".*?")';
				}
			);
		};
	};
}



More information about the textmate mailing list