Lexikalische Analyse mit FLEX



  • Kennt sich hier jemand mit dem Tool Flex aus?

    Folgendes Codefragment funktioniert nicht korrekt bzw. ich habe das falsch definiert.
    Und zwar ab Zeile 51-57 gibt es Probleme. Und zwar wird nur der Teile Zeile 55-57 ausgeführt.
    Das obere wird nicht beachtet.
    Wenn ich nur das Obere(Zeile 51-53) im Quellcode, also ihne Zeile 55-57 habe, dann funktioniert auch das eigentlich korrekt und es wird das Erwartete ausgegeben.

    Zum eigentlichen Ziel: ich möchte aus einer xhtml datei aus einem validen a-tag das Attribut href=""... und den Linktext extrahieren und ausgeben. Für den Linktext gilt dass das href-Attribut in dem a-tag enthalten ist und alle weitere Attribute sollen einfach ignoriert werden.

    Ganz unten stehtich die entspechende Test HTML Datei.

    %option noyywrap yylineno nounput noinput never-interactive
    
    LETTER   [b-z]
    WS       [[:space:]]
    SLASH    [/]
    LINKTEXT ([!#-;|=-~|\n|äü]*{WS}*)*
    ALPHA    [a-zA-Z][a-zA-Z0-9]*{WS}*
    EQ       [=]
    QUOTES   ["]
    ATTR     {ALPHA}*{EQ}{QUOTES}{ALPHA}*{QUOTES}{WS}*
    HREFATTR "href="{QUOTES}{LINKTEXT}{QUOTES}{WS}*
    ATAGS    "<a"{WS}*{ATTR}*{HREFATTR}{ATTR}*">"{LINKTEXT}"</a"[ \n\t\r]*">"
    
    
    %start atag
    %start LINK
    
    
    %{
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MYEOF      EOF
    #define TOKEN_URL  257
    #define TOKEN_TEXT 258
    
    #ifndef YYSTYPE
    #define YYSTYPE yystype
    typedef char* yystype;
    #endif
    
    YYSTYPE yylval;
    
    
    
    %}
    
    
    
    
    %%
    
    {WS}*		
    <<EOF>>	 	  return MYEOF;	
    
    
    .            {}
    
    
    <INITIAL>"<a"{WS}*{ATTR}*{HREFATTR}{ATTR}*>	BEGIN LINK;
    <LINK>{LINKTEXT}	{yylval=strdup(yytext);return TOKEN_TEXT;}
    <LINK>"</a"[ \n\t\r]*">"	BEGIN INITIAL;
    
    <INITIAL>"<a"	BEGIN atag;
    <atag>{HREFATTR}	{yylval=strdup(yytext);return TOKEN_URL;}
    <atag>">"		BEGIN INITIAL;
    
    
    
    
    
    %%
    
    
    
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    		<title>Aufgabe 4</title>
    	</head>
    	<body>
    		<h1><a name="Ueberschrift">Praktische Informatik III</a></h1>
    		<p>Zu ignorierender text am Anfang</p>
    
    		<p><a href="http://www2.informatik.hu-berlin.de/sam" name="Werbung">Lehrstuhlseiten - sollten ausgegeben werden.</a
    		></p>
    		<p>Zu ignorierender Text in der Mitte</p>
    		<p><a name="Keine URL sondern nur einfacher Anker">Dieser Text soll ignoriert werden, da der Anker keine URL enthält</a   ></p>
    
    		<p>Zu ignorierender Text in der Mitte</p>
    		<p><a  name="Grundwissen" href="http://www.userfriendly.org">Userfriendly - sollte jeder Informatiker kennen (und daher sollte dieser Text auch ausgegeben werden :-)</a   ></p>
    
    		<p>Zu ignorierender Text am Ende</p>
    	</body>
    </html>
    
    
    


  • und daran ist jetzt genau was C?



  • @Wade1234 sagte in Lexikalische Analyse mit FLEX:

    und daran ist jetzt genau was C?

    die zeilen 21 bis 31 🙂



  • Das meiste ist natürlich lex-Code .

    Ich dachte es könnte in die Rubrik C passen.



  • Wenn du noch eine main dazuliefern würdest, wäre das hilfreich.



  • Dieses C Programm ruft the lexer auf.
    Diese C Datei darf nicht verändert werden.

    
    #include <stdio.h>
    #include <stdlib.h>
    #include "urlscanner.h"
    
    yystype yylval;
    
    int main(int argc, char* argv[]) {
    	int token;
    	
    	if (argc != 2) yyin = stdin;
    	else {
    		yyin = fopen(argv[1], "r");
    		if (yyin == 0) {
    			fprintf(stderr,
                        "Fehler: Konnte Datei %s nicht zum lesen oeffnen.\n",
                        argv[1]);
    			exit(-1);
    		}
    	}
    
    	while ((token = yylex()) != MYEOF) {
    		if (token == TOKEN_URL) {
    			
    			printf("Line: %3d\tURL:  %s\n", yylineno, yylval);
    		} else if (token == TOKEN_TEXT) {
    			printf("Line: %3d\tTEXT: %s\n", yylineno, yylval);
    		} else {
    			printf("Error\n");
    		}
    	}
    	
    	return 0;
    }
    
    
    


  • #include <stdio.h>
    #include <string.h>
    char*s=
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">"
    "<html>"
    	"<head>"
    		"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
    		"<title>Aufgabe 4</title>"
    	"</head>"
    	"<body>"
    		"<h1><a name=\"Ueberschrift\">Praktische Informatik III</a></h1>"
    		"<p>Zu ignorierender text am Anfang</p>"
    ""
    		"<p><a href=\"http://www2.informatik.hu-berlin.de/sam\" name=\"Werbung\">Lehrstuhlseiten - sollten ausgegeben werden.</a"
    		"></p>"
    		"<p>Zu ignorierender Text in der Mitte</p>"
    		"<p><a name=\"Keine URL sondern nur einfacher Anker\">Dieser Text soll ignoriert werden, da der Anker keine URL enthält</a   ></p>"
    ""
    		"<p>Zu ignorierender Text in der Mitte</p>"
    		"<p><a  name=\"Grundwissen\" href=\"http://www.userfriendly.org\">Userfriendly - sollte jeder Informatiker kennen (und daher sollte dieser Text auch ausgegeben werden :-)</a   ></p>"
    ""
    		"<p>Zu ignorierender Text am Ende</p>"
    	"</body>"
    "</html>";
    
    int main()
    {
        FILE *f=fmemopen(s,strlen(s),"r");
        char a[1000],b[1000],c[1000],d[1000];
        while( fscanf(f,"%999s",a)==1 )
            if(strstr(a,"<a")==a+strlen(a)-2)
                if(fscanf(f,"%999[^>]>",b)==1)
                    if(strstr(b,"href="))
                        if(1==sscanf(strchr(strstr(b,"href="),'\"')+1,"%[^\"]\"",c))
                        {
                            if(fscanf(f,"%999[^<]<",d)==1)
                            printf("%s\n\t%s\n",c,d);
                        }
        fclose(f);
        return 0;
    }
    

    https://onlinegdb.com/B1ViDPsZU

    Feature: wenn der Tagtext leer ist, wird href auch gleich ignoriert.



  • Die Zeilen werden "ausgeführt" (du bist dir aber im klaren, dass eine flex-Spezifikation kein Programm ist?). Die Regel mit <atag>{HREFATTR} matcht nie, weil ein a-tag mit href-Attribut immer auch schon von der anderen Regel aufgefangen wird.

    Das gesagte gilt, wenn man die offensichtliche Korrektur durchführt und die catch-all-Regel nach unten verlegt. flex warnt sonst auch, dass eine Regel nie matchen wird.



  • Hallo, danke für die Tipps.

    Habe das jetzt etwas geändert und ich bekomme fast die korrekte Ausgabe.
    Es soll ja nur die a-tags mit url also href=... und den Linktext dazu .
    Allerdings gibt er auch die a-tags wo kein href-Attribut vorhanden ist und das soll es nicht.

    Habe eine zweite Umgebung hinzugefügt <LINK>.

    %%
    
    {WS}*		
    <<EOF>>	 	  return MYEOF;	
    
    
    
    
    
    
    
    <INITIAL>"<a"	BEGIN atag;
    <atag>{ATTR}*
    <atag>{HREFATTR}	{yylval=strdup(yytext);return TOKEN_URL;}
    <atag>{ATTR}*
    <atag>">"		BEGIN LINK;
    
    
    <LINK>{LINKTEXT}	{yylval=strdup(yytext);return TOKEN_TEXT;}
    <LINK>"</a"[ \n\t\r]*">"	BEGIN INITIAL;
    
    
    .            {}
    
    %%
    


  • Hallo,

    so funktioniert es nun.

    Also Problem gelöst und vielen Dank für die Hilfestellung.

    Grüße

    %option noyywrap yylineno nounput noinput never-interactive
    
    LETTER   [b-z]
    WS       [[:space:]]
    SLASH    [/]
    LINKTEXT ([!#-;|=-~|\n|äü]*{WS}*)*
    ALPHA    [a-zA-Z][a-zA-Z0-9]*{WS}*
    EQ       [=]
    QUOTES   ["]
    ATTR     {ALPHA}*{EQ}{QUOTES}{ALPHA}*{QUOTES}{WS}*
    HREFATTR "href="{QUOTES}{LINKTEXT}{QUOTES}{WS}*
    ATAGS    "<a"{WS}*{ATTR}*{HREFATTR}{ATTR}*">"{LINKTEXT}"</a"[ \n\t\r]*">"
    
    
    %start atag
    %start LINK
    
    
    %{
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    
    #define MYEOF      EOF
    #define TOKEN_URL  257
    #define TOKEN_TEXT 258
    
    #ifndef YYSTYPE
    #define YYSTYPE yystype
    typedef char* yystype;
    #endif
    
    YYSTYPE yylval;
    bool is_href;
    
    
    
    %}
    
    
    
    
    %%
    
    	
    <<EOF>>	 	  return MYEOF;	
    
    
    
    
    
    
    
    <INITIAL>"<a"	BEGIN atag;
    
    <atag>{HREFATTR}	{is_href = true;yylval=strdup(yytext);return TOKEN_URL;}
    
    <atag>">"		BEGIN LINK;
    <LINK>{LINKTEXT}	{if(is_href){yylval=strdup(yytext);return TOKEN_TEXT;}}
    <LINK>"</a"[ \n\t\r]*">"	{is_href = false;BEGIN INITIAL;}
    
    {WS}*	
    .            {}
    
    %%
    

Log in to reply