2013-04-29 21 views
6

Ich arbeite mit Ragel, um FSAs zu bewerten, und ich möchte eine Benutzeraktion einbetten, die ausgeführt wird, wenn mein Computer die Eingabe beendet. Ich muss diese Aktion ausführen, unabhängig davon, ob die Maschine in einem akzeptierenden Zustand endet oder nicht. Ich habe dieses modifizierten Beispiel von der Führungs Ragel genommen, die zeigt, was ich für:Wie man Ragel EOF Aktionen funktioniert

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

Mein Ziel für dieses Beispiel ist für res 1 zu sein, wenn der Eingang entweder ‚foo‘ oder ‚bar‘ ist, während fertig ist 1 unabhängig von der Eingabe. Ich kann das nicht zur Arbeit bekommen - fertig scheint 1 zu sein, wenn res 1 ist, und 0 wenn res 0 ist.

Jede Hilfe wäre toll.

Antwort

1

Versuchen Sie folgendes:

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

EOF Aktion statt, wenn p == pe == eof stattfinden wird. Eine andere wichtige Sache ist, dass, wenn Ihre Zustandsmaschine nicht irgendein Staat passen kann, der Zustand zum Fehler geht und das Match stoppt, was bedeutet, dass Sie nie zum Ende gehen können.

Mal sehen, wenn Sie foo1 eingeben. Beim Parsen zu o ist alles in Ordnung. Der nächste Zeichensatz 1 kann jedoch keinem von Ihnen angegebenen Zustand entsprechen, daher tritt ein Fehler auf. Sie können die eof-Aktion nie erfüllen. So ist die Variable res und finish beide 0.

Wenn Sie 10 eingeben, ist alles in Ordnung. Der Staat kann bis zum Ende gehen. Also die eof-Aktion findet statt.

Sie können das Fehler Aktion zu sehen, was passiert:

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

Und Sie können diesen Code versuchen, Ihre Bedürfnisse zu erfüllen:

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