2013-04-29 3 views
6

Я работаю с Ragel для оценки FSA, и я хочу внедрить действие пользователя, которое запускается всякий раз, когда моя машина завершает тестирование ввода. Мне нужно, чтобы это действие выполнялось независимо от того, закончилась ли машина в принимающем состоянии или нет. У меня есть этот модифицированный пример, взятый из руководства Ragel, который иллюстрирует то, что я иду:Как получить действия Ragel EOF, работающие

#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; 
} 

Моя цель для этого примера для разрешения быть 1, когда вход либо «Foo» или «бар», в то время как завершено - 1 независимо от ввода. Я не могу заставить это работать, хотя - закончено, кажется, 1, когда res равно 1, и 0, когда res равно 0.

Любая помощь была бы потрясающей.

ответ

1

Попробуйте это:

main := ( 
    'foo' 0 @2 @{ res = 1; } | 
    'bar' 0 @2 @{ res = 1; } | 
    any* 
    ) @{ finished = 1; }; 
3

Действие ВФ будет иметь место, когда p == pe == eof. Еще одна важная вещь: когда ваш конечный автомат не может соответствовать , состояние, состояние переходит к ошибке, и совпадение остановится, а это значит, что вы никогда не сможете дойти до конца.

Посмотрим, когда вы введете foo1. При разборе o все в порядке. Howerver следующий charactor 1 не может соответствовать указанному вами состоянию, поэтому возникает ошибка. Вы никогда не сможете встретить действие eof. Таким образом, переменная res и finish равна 0.

Когда вы вводите foo, все в порядке. Государство может пойти до конца. Таким образом, действие eof происходит.

Вы можете установить действие ошибки, чтобы увидеть, что происходит:

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

И вы можете попробовать этот код, чтобы удовлетворить ваши потребности:

%%{ 
    main := (('foo' | 'bar') 0 @{ res = 1; } | any*) $/{ finished = 1; }; 
}%%