[ragel-users] Machine not running terminating actions

Adrian Thurston thurs... at cs.queensu.ca
Wed Jan 3 03:21:59 UTC 2007


Hi Matt,

You're parser is coming along nicely :) Here are some more tips.

When it comes to ordering actions on the same character, just remember 
that there is an outer-inner ordering. It goes outer start actions, 
inner start actions, inner rest actions, outer rest actions. "rest" 
meaning finishing, leaving, and all actions. It seems that what you have 
now is right.

Leaving actions (%) only fire on character transitions. What is 
happening is that at the end of the input the machine is just exiting. 
There is no character to cause the action to get executed. If you embed 
an eof action (using %eof exit_diff) at the same places that you've 
specified the leaving actions (%exit_diff) and you write the eof switch 
(with %%write eof;) then they will fire.

Alternatively you can specify a termination character (perhaps 0) at the 
end of main and send it once the input is done. That will 'flush' the 
leaving actions.

You can try it out with something simple like the following. I find the 
smaller machines are easier to reason about and what you learn 
generalizes well.

%%{
	machine tmp;
	action e1 {}
	action e2 {}

	sub = ( 's' [^\n]* '\n' ) %e1 %eof e1;
	fun = ( 'f' sub* ) %e2 %eof e2;

	main := fun*;
}%%

I'm not sure what you intend with the following, maybe some explicitly 
specified lookahead? I would remove it though because I don't think it's 
necessary and it doesn't seem to be compatible with my advice above.

( ignoreCode | hunkEndChar @{ fhold; } );

In general, it's advisable to avoid fhold unless you're about to jump 
somewhere using fgoto or you're really sure of what you're doing. The 
problem is that if you union a machine that has an fhold in it with 
something else, the fhold will also apply to the something else when you 
probably don't want it to. It can make things really complicated.

Cheers,
  Adrian

Matt Mower wrote:
> Hi again.
> 
> With your help I've been able to iron out many of the wrinkles in my
> diff parser and have something approximating a good parse of arbitrary
> svn diff output. One thing has me stumped though. The actions for the
> last hunk of the last diff are not being fired.
> 
> Here is my machine:
> 
> ### expressions
> 
>     lineChar = ( print | space ) - '\n';
>     
>     nbsp = space - '\n';
>     
>     line = ( ' ' | '-' | '+' ) @{ fhold; } lineChar* '\n'+ ;
>     
>     ignore_line = lineChar* '\n';
> 
>     ignoreCode = '\\' line;
>     separator = '='+ '\n';
>     hunkEndChar = print - ( space | '+' | '-' );
>     
>     oldFile = '---' ignore_line;
>     newFile = '+++' ignore_line;
>     
>     hunkHeader = '@@' print+ '@@' '\n'+;
>     
>     hunkBody = ( line )+ ( ignoreCode | hunkEndChar @{ fhold; } );
>     
>     hunk = hunkHeader >enter_hunk hunkBody %exit_hunk;
>     
>     fileName = ( lineChar+ ) >mark %copy_to_filespec;
>     
>     fileSpec = "Index:" nbsp+ fileName '\n'+;
>     
>     diffHeader = ( fileSpec separator oldFile newFile );
>     diffBody = hunk* %exit_diff;
>     
>     diff = diffHeader >enter_diff diffBody;
>     
> #    main := diff* $!error $~track;
> #    main := diff* $!error;
>     main := diff*;
> 
> It's the result of much tinkering to get the actions to fire in the
> right sequence (I have a lot of problems with exit_diff actions firing
> before corresponding exit_hunk's and so forth).
> 
> It correctly parses into each diff and each hunk within in. Where it
> falls down, as I say, is that exit_hunk and exit_diff are not fired
> for the last parsed hunk of the last diff.
> 
> I've attached a graph showing the diffBody machine as well as the full
> .dot and the parser itself.
> 
> Any help would be much appreciated.
> 
> Thanks,
> 
> Matt
> 
> 
> ------------------------------------------------------------------------
> 



More information about the ragel-users mailing list