How to get Ragel EOF actions working
Asked Answered
M

2

6

I'm working with Ragel to evaluate FSAs, and I want to embed a user action that runs whenever my machine finishes testing the input. I need this action to run regardless of whether or not the machine ends in an accepting state or not. I have this modified example taken from the Ragel guide that illustrates what I'm going for:

#include <string.h>
#include <stdio.h>

%%{
    machine foo;
    main := ( 'foo' | 'bar' ) 0 @{ res = 1; } $/{ finished = 1; };
}%%
%% write data;
int main( int argc, char **argv ) {
    int cs, res = 0, finished = 0;
    if ( argc > 1 ) {
        char *p = argv[1];
        char *pe = p + strlen(p) + 1;
        char* eof = pe;
        %% write init;
        %% write exec;
    }

    printf("result = %i\n", res );
    printf("finished = %i\n", finished);

    return 0;
}

My goal for this example is for res to be 1 when the input is either 'foo' or 'bar', while finished is 1 no matter the input. I can't get this to work though - finished seems to be 1 when res is 1, and 0 when res is 0.

Any help would be awesome.

Marlinmarline answered 29/4, 2013 at 7:21 Comment(0)
H
3

The eof action will take place when p == pe == eof. Another important thing is that when your state machine can't match any state, the state will go to error and the match will stop, which means you can never go to the end.

Let's see when you input foo1. When parsing to o, everything is ok. Howerver the next charactor 1 can't match any state you specify, so an error occurs. You can never meet the eof action. So the variable res and finish is both 0.

When you input foo, every thing is ok. The state can go to the end. So the eof action take place.

You can set the error action to see what happens:

%%{
    main := ( 'foo' | 'bar' ) 0 @{ res = 1; } $err{ printf("error : %c", fc);} $/{ finished = 1; };
}%%

And you may try this code to meet your needs:

%%{
    main := (( 'foo' | 'bar' ) 0 @{ res = 1; } | any* ) $/{ finished = 1; };
}%%
Handshaker answered 9/6, 2013 at 11:5 Comment(0)
J
1

Try this:

main := ( 
    'foo' 0 @2 @{ res = 1; } | 
    'bar' 0 @2 @{ res = 1; } |
    any*
    ) @{ finished = 1; };
Joliejoliet answered 6/6, 2013 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.