Lex-Analysator zum Erzeugen einer Datei, die keine Liste von Programmen mit lexikalischen Fehlermeldungen erzeugt - Linux, Ubuntu, Compiler-Konstruktion, Flex-Lexer, Lex

Ich versuche einen Lexanalysator zu bauenerstellt eine Liste des Programms mit lexikalischen Fehlermeldungen, die nach der Zeile enthalten sind, in der sie auftreten. Mit anderen Worten, wenn das Lesen des Charakters kein Token starten kann, wird dies als Fehler betrachtet. Es soll auch eine Datei mit den Lexem-Token-Paaren erzeugen, damit es überprüfen kann, ob der Analysator funktioniert. Ich kann eine Ausgabedatei erhalten, aber es funktioniert nicht richtig, als wenn ich versuche, es auszuführen, es gibt mir nur einen Befehlsbildschirm, wie ich in der Datei arbeite. Hier ist mein Code für meine Scanner-Datei, die einen Eingabetext liest:

%{
#include <stdio.h>
#include <ctype.h>
#include "tokens.h"

void toTitle(char* yytext, int yyleng);
%}

%option noyywrap

ws      [ trn]+
quoted      ".*"
letter      [A-Za-z]
digit       [0-9]
word        {letter}+(-{letter}+)?
number      {digit}+
punc        [,:;()]
begin       { ECHO; return(begin);}
boolean     { ECHO; return(BOOLEAN);}
else        { ECHO; return(ELSE); }
end     { ECHO; return(END); }
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
function    { ECHO; return(FUNCTION); }
if      { ECHO; return(IF); }
is      { ECHO; return(IS); }
integer     { ECHO; return(INTEGER); }
real        { ECHO; return(REAL); }
returns     { ECHO; return(RETURNS); }
then        { ECHO; return(THEN); }
line        [n]

%%

"&&"                    { return(LOGOPAND); }
"||"                    { return(LOGOPOR); }
"!="                    { return(LOGOPNOT); }
[ tn]                 ;
{ws}                    { ECHO; }
"<"                     { ECHO; return(RELOP); }
"="                     { ECHO; return(RELOP); }
"/="                    { ECHO; return(RELOP); }
">"                     { ECHO; return(RELOP); }
">="                    { ECHO; return(RELOP); }
"<="                    { ECHO; return(RELOP); }
"*"                     { ECHO; return(MULTOP); }
"/"                     { ECHO; return(MULTOP); }
"+"                     { ECHO; return(ADDOP); }
"-"                     { ECHO; return(ADDOP); }
"true"                  { ECHO; return(BOOLLITERAL); }
"false"                 { ECHO; return(BOOLLITERAL); }
{digit}                 { ECHO; return(I_LITERAL); }
{digit}+"."{digit}*             { ECHO; return(R_LITERAL); }
begins                  { ECHO; return(BEGINS); }
{punc}                  { ECHO; return yytext[0]; }
{quoted}            { ECHO; }
{word}              {toTitle(yytext, yyleng); }
{number}            { ECHO; }

%%

void toTitle(char* yytext, int yyleng)
{

}

void tokenCount(int token)
{
while (token = yylex())
fprintf(yyout, "%d %sn", token, yytext);
}

int main() {
while (yylex());
return 0;

}

Ich habe eine Header-Datei mit meinen definierten Token:

#ifndef TOKENS_H
#define TOKENS_H

typedef enum Tokens {RELOP = 256, ADDOP = 257, MULTOP = 258, LOGOPNOT = 259, BOOLLITERAL = 260, I_LITERAL = 261, R_LITERAL = 262, IDENTIFIER = 263, PUNCTUATION = 264, BEGINS = 265, BOOLEAN = 266, ELSE = 267, END = 268, ENDIF = 269, FUNCTION = 270, IF = 271, IS = 272, INTEGER = 273, REAL = 274, RETURNS = 275, THEN = 276, LOGOPAND = 277, LOGOPOR = 278, begin = 279} Tokens;

#endif

Meine Ausgabe sollte ungefähr so ​​aussehen:

   1  -- Simple program with one function
2
3  function main a: integer returns integer;
4      b: integer is a * 2;
5  begin
6      if a <= 0 then
7          b + b;
8      else
9    b * b;
10      endif;
11  end;

Compiled Successfully

Antworten:

2 für die Antwort № 1

Ich habe bemerkt, dass dies die dritte Frage ist, die Sie habenSie haben das gleiche Problem angesprochen und vermuten, dass Sie möglicherweise nicht vollständig verstehen, wie Sie diese Aufgabe oder die Dokumentation und die Antworten, die Sie bisher gesehen haben, erledigen können. Stackoverflow bietet Anleitungen und Standards zu den besten Möglichkeiten, eine Frage zu formulieren Service von den vielen Weltklasseexperten, die hier verfügbar sind, wie diese Anleitung zum Stellen von Fragen zu StackOverflow. Ich sehe, dass Sie ein Anfänger sein könnten, und im Falle Ihres Problems wäre es zu Ihrem Vorteil gewesen, zu lernen wie man das Problem vereinfacht. Ich werde zeigen, wie Sie das Problem vereinfachen können, indem Sie Ihren Code als Beispiel verwenden und so zu einer guten Beschreibung des Problems und schließlich der Lösung gelangen.

Das Problem mit Ihrem Code, ist das gleiche Problem in den Kommentaren von @rici zu Ihrem identifiziert frühere Frage "Diese Lex-Datei sieht aus, als wäre sie aus zufälligen Schnipsel mit verschiedenen Stilen eingefügt worden."

Gehen wir zurück zum Flex Handbuch und schauen Sie sich die Gesamtstruktur eines Flex-Programms an:

     definitions
%%
rules
%%
user code

Die Position der %% Linien teilen den Code in drei Abschnitte, und damit was Sie vor den %% und was du nachgestellt hast %% ist wirklich wichtig.

Jetzt in der Antwort auf deine letzte Frage schrieb @nlu:

ECHO ist eine spezielle Aussage, die nur im Bereich Aktionen verwendet werden kann.

und dann hast du geantwortet:

Ich korrigierte den Code, indem ich alle reservierten Wörter und ihre Aktionen in den ersten Teil vor der %% Syntax

Leider hast du diesen Vorschlag falsch gelesen undlinker Code für den Abschnitt rules / action im Deklarationsteil. Leider hat dies nicht dazu geführt, dass Ihnen der Flex hilfreiche Nachrichten gab, da es ein sinnvolles Flex-Programm geblieben ist. nur nicht die, die du erwartet hast!

Um dies zu verdeutlichen, können Sie keine Aktionen ausführen, einschließlich eines ECHOvor dem ersten %%, denn dann wäre es im Definitionsbereich. Sie müssen nach Der Erste %% so sind die im Abschnitt Regeln / Aktionen. Daher sind alle diese Zeilen am falschen Ort:

begin       { ECHO; return(begin);}
boolean     { ECHO; return(BOOLEAN);}
else        { ECHO; return(ELSE); }
end     { ECHO; return(END); }
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
function    { ECHO; return(FUNCTION); }
if      { ECHO; return(IF); }
is      { ECHO; return(IS); }
integer     { ECHO; return(INTEGER); }
real        { ECHO; return(REAL); }
returns     { ECHO; return(RETURNS); }
then        { ECHO; return(THEN); }

Wie konntest du das selbst debuggen? Wie es in den SO-Hilfeseiten vorgeschlagen wird: vereinfachen. Ich werde anhand eines Beispiels zeigen, wie das möglich ist. Wenn Sie das Problem auf eine Sprache mit nur einem Schlüsselwort reduziert haben, sagen wir begin und einige Leerzeichen, und löschte alle anderen Zeilen, für alle anderen Schlüsselwörter und Symbole, dann wäre es ein viel einfacheres Problem zu adressieren. Versuchen wir das mit Ihrem Code:

%option noyywrap

ws      [ trn]+
begin       { ECHO; return(begin);}
line        [n]
%%
[ tn]                 ;
{ws}                    { ECHO; }
begins                  { ECHO; return(BEGINS); }
%%

int main() {
while (yylex());
return 0;
}

Sie werden bemerken, dass ich gerade alle Zeilen gelöscht habedie sich auf andere Schlüsselwörter und Symbole beziehen, da sie das Bild mit einem Wirrwarr zusätzlicher Zeilen verwechseln. Genau das tun Experten und professionelle Programmierer in ihrer täglichen Problemlösung. Du denkst nicht, dass wir eine psychische Art haben, Fehler zu finden, oder? Das ist die Fähigkeit, die mit der Übung einhergeht.

Konzentriere dich jetzt darauf einfacher Programm, es gibt Dinge, die wir sehen können. Es kompiliert und läuft übrigens, und sein ganzer Code (einfach einfacher). Wenn wir es ausführen, das Schlüsselwort begins bekommt ECHOed aber das Stichwort begin nicht. Da ist ein Hinweis. Wenn die Zeile für begin wurde nach unten verschoben %% es würde genauso funktionieren wie die begins Linie hat. Aber warum akzeptiert Flex das schlechte Programm und gibt Ihnen keinen hilfreichen Fehler? Dies liegt daran, dass diese Zeile immer noch ein ist gültige Definition eines Lexem nach Flex-Regular-Expression-Notation. Was Sie definiert haben, war ein Lexem genannt begin (auf die Sie mit der Notation zugreifen {begin} im Abschnitt Regeln), der als übereinstimmend definiert ist Zeichenfolge "{ ECHO; return(begin);}". Da Sie diese Zeichenfolge jedoch nie eingegeben haben und den Namen auch nie verwendet haben {begin} Dieses Fragment der Definition wird nie benutzt.

Es gibt auch die Frage: Hat Ihre Sprache wirklich ein Stichwort namens begin und ein anderer rief an begins. Scheint fischig zu mir. Ein weiterer Fehler vielleicht? Ähnlich können wir dasselbe mit dem weißen Raum sehen. Sie haben versucht, eine neue Zeile zu finden n an drei Orten. Dies wird verwirrend sein, da Sie nicht sicher sein können, welche der Definitionen und Aktionen bei einem Zeilenumbruch ausgeführt werden. Da Sie die Zeilen zu einem bestimmten Zeitpunkt nummerieren möchten, könnte dies ein Problem für Sie sein. Du hast es auch gesagt, um es zu ignorieren und ECHO Leerzeichen. Was soll es sein? Es kann nicht beides. Von Ihrer Beispielausgabe wollten Sie vielleicht geantwortet haben. All diese Korrekturen an die einfach Programm bekommen wir das:

%option noyywrap

ws                      [ tr]+
line                    [n]
%%
{ws}                    { ECHO; }
begin                   { ECHO; return(BEGIN); }
%%

int main() {
while (yylex());
return 0;
}

Das funktioniert für eine einfache Sprache mit nur dem Schlüsselwort begin. Alles, was wir jetzt tun müssen, ist, die anderen Teile langsam und vorsichtig wieder einzusetzen. Als Nächstes fügen wir das Keyword hinzu endif zum Code, und wir bekommen:

%option noyywrap

ws                      [ tr]+
line                    [n]
%%
{ws}                    { ECHO; }
begin                   { ECHO; return(BEGIN); }
endif       void toTitle(char* yytext, int yyleng){ ECHO; return(ENDIF); }
%%

int main() {
while (yylex());
return 0;
}

Dies jedoch kompiliert nicht. Das Stück Code void toTitle(char* yytext, int yyleng) sieht wie eine falsche Paste aus, wenn du den Code zusammen mit den Lösungen anderer Leute hackst - Dah!.

Nun, das hat sich mit all den Fehlern in Ihrem erledigtCode, und wenn Sie sie verstanden haben, konnten Sie Ihren ganzen Code arbeiten lassen. Jetzt müssen Sie etwas mehr programmieren, bevor Sie die gesamte Aufgabe abgeschlossen haben. Sie müssen Zeilenzählung, Handhabung von Variablen und Konstanten und ein paar andere Bits hinzufügen und dann sind Sie fertig.

Ich hoffe, Sie fanden das hilfreich und führen dazu, dass Sie den Rest Ihrer Programmierarbeit lösen können.


Am beliebtesten