30 Stimmen

Schwierigkeiten, Kommentare im C-Stil in Flex/Lex zu erhalten

Ich möchte eine Regel in Flex machen, um einen C-Stil Kommentar wie /* */ zu konsumieren

Ich habe Folgendes

c_comment "/*"[\n.]*"*/"

Aber es wird nie ein Treffer erzielt. Irgendeine Idee, warum? wenn Sie mehr von meinem Code benötigen, lassen Sie mich bitte wissen, und ich werde die ganze Sache einreichen. Danke an jeden, der antwortet.

48voto

zneak Punkte 129366

Ich schlage vor, Sie verwenden Startbedingungen stattdessen.

%x C_COMMENT

"/*"            { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>\n   { }
<C_COMMENT>.    { }

Bitte beachten Sie, dass es darf nicht ein beliebiges Leerzeichen zwischen den <condition> und die Regel.

%x C_COMMENT definiert den Zustand C_COMMENT, und die Regel /* lässt ihn starten. Sobald er gestartet ist, */ kehrt es in den Ausgangszustand zurück ( INITIAL ist vordefiniert), und alle anderen Zeichen werden einfach ohne eine besondere Aktion konsumiert. Wenn zwei Regeln übereinstimmen, nimmt Flex diejenige, die am längsten übereinstimmt, so dass die Punktregel nicht verhindert, dass */ von Matching. Die Website \n Regel ist notwendig, weil ein Punkt entspricht allem außer einem Zeilenumbruch .

En %x Definition ist C_COMMENT ein exklusiver Staat was bedeutet, dass der Lexer nur auf Regeln passt, die "getaggt" sind <C_COMMENT> sobald es den Staat betritt.

Hier ist ein kleines Beispiel Lexer die diese Antwort umsetzt, indem sie alles ausgibt, außer dem, was darin steht /* comments */ .

9voto

user1747935 Punkte 352

Hier ist ein Beispiel, nur für den Fall, dass jemand verwirrt ist, wie die Antwort von zneak zu verstehen ist:

(Im Grunde setzen Sie "%x C_COMMENT" in den ersten Abschnitt und den Rest in den zweiten Abschnitt, wie in seinem hilfreichen Link erklärt)

foo.l

%{
// c code..
%}
%x C_COMMENT

%%
"/*"            { BEGIN(C_COMMENT); }
<C_COMMENT>"*/" { BEGIN(INITIAL); }
<C_COMMENT>.    { }

%%
// c code..

Hoffentlich hilft das jemandem! Tiff

7voto

paxdiablo Punkte 809679

Ich bin mir nicht sicher, warum es nicht aufgegriffen wird, aber ich weiß, dass ein solches Muster große lexikalische Elemente erzeugen kann. Es ist effizienter, nur die Startkommentarmarke zu erkennen und alles in den Bitbucket zu werfen, bis Sie die Endmarkierung finden.

Diese Seite hat Code, der das tut:

"/*" {
    for (;;) {
        while ((c = input()) != '*' && c != EOF)
            ; /* eat up text of comment */
        if (c == '*') {
            while ((c = input()) == '*')
                ;
            if (c == '/')
                break; /* found the end */
        }
        if (c == EOF) {
            error ("EOF in comment");
            break;
        }
    }
}

2voto

Mugen Punkte 6795

Ich glaube, diese Lösung ist einfacher:

"/*"((\*+[^/*])|([^*]))*\**"*/"

1voto

mwag Punkte 2818

Ich habe mehrere der vorgeschlagenen Lösungen ausprobiert, und hier sind die Ergebnisse.

  • Ich konnte die C_COMMENT-Lösung, die die meisten Stimmen erhalten hat und gut aussieht, in der Praxis nicht zum Laufen bringen (einer der Kommentare dazu erklärt zumindest einen Grund dafür). Sie sollte heruntergestuft werden und sicherlich nicht die am höchsten bewertete Lösung sein
  • Die Lösung von Mugen schien in allen Codes zu funktionieren, in denen ich sie ausführte
  • Ich konnte die Lösung von Andrey nicht einmal in lex kompilieren lassen. Ich habe mir die referenzierte Website angesehen und die Verwendung von Mustern von dort hat nicht geholfen
  • die Antwort von paxdiablo funktionierte und hatte den Vorteil, dass sie leicht zu lesen war. Ich habe sie dann wie folgt geändert:

    "/\*" { int c1 = 0, c2 = input();
           for(;;) {
             if(c2 == EOF) break;
             if(c1 == '\*' && c2 == '/')
               break;
             c1 = c2;
             c2 = input();
           }
         }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X