Übungsblatt2 ============= Author: Jan Schäfer Date: 2011-05-09 12:04:25 CEST Table of Contents ================= 1 Übungsblatt 2 1.1 Aufgabe 1 1.2 Aufgabe 2 1 Übungsblatt 2 ~~~~~~~~~~~~~~~~ 1.1 Aufgabe 1 -------------- + Lösungsweg!!! Nur eine Gruppe! + Wichtig: Zustandsnamen beim DFA als Mengen! + Achtung mit . in REs! . ist oft vordefinierte Character-Klasse, die *alles* matched Extra-Warnung: meistens matched . *nicht* line terminators! => In der Regel konfigurierbar + Fragen * Frage 1 - Gibt es immer einen DFA? Wenn, ja, warum? NFA ist endlich * Frage 2 - Gegeben ein NFA mit n Zuständen, wieviele Zustände hat der DFA maximal? 2^n + Warum? P(A) kann als n-bit Zahl repräsentiert werden * Frage 3 - Ist der DFA alleine genug für einen Scanner? Nein, es müssen auch die Token zurückgegeben werden (an die Endzustände schreiben) * Frage 4 - Was wenn mehrere Token matchen? - Regeln definieren, z.B. das erste in der Definitionsliste * Frage 5 - Ist der erzeugte DFA immer optimal? Nein * Frage 6 - Wie kann ich den DFA optimieren? Finde äquivalente Zustände und vereinige sie + Wann sind Zustände äquivalent? 1. Beide final/non-final 2. Für jedes Symbol s haben beide den gleichen Folgezustand * Frage 7 - Reicht das? Nein, es geht immer noch einfacher 1.2 Aufgabe 2 -------------- + a) JFLex-Datei * Klammern und CO - Lösung 1 SZE = [(),{}.+-\\*/;] {SZE} { return new Token(Token.SPECIAL); } - Lösung 2 "(" { return new Token(Token.LPAREN); } ... * Whitespaces WHITESPACE = [ \t\n\r] * New Lines NEWLINE = \r|\n|\r\n * Identifier - Lösung 1 IDENT = [a-zA-Z$_][a-zA-Z$_0-9]+ + Problem matched $ (in Java erlaubt, aber nicht laut Blatt) - Lösung 2 DIGIT = [0-9] LETTER = [a-zA-Z] IDENT = ({LETTER}|_)({LETTER}|{DIGIT}|_)* - Lösung 3 BU = [a-zA-Z_] BUZI = {BU}|[0-9] IDENT = {BU}{BUZI}* - Identifier String? yytext() IDENT { return token(TokenType.IDENTIFIER, yytext()); } * Integer - Lösung 1 INTEGER = [+-]?[0-9]+ + Problem 00005 - Lösung 2 INTEGER = [+-]?(0|[1-9][0-9]*) - Vorzeichen? 4 + 3 4 +3 + b) Kommentare * Lösung 1 COMMENT = "/*" ([^*] | "*"[^/])* "*"? "*/" - Problem /* **/ /* */ * Lösung 2 COMMENT = "/*" ( [^*] | "*"[^/*])* "*"? "*/" - Problem /** ** **/ * Lösung 3 COMMENT = "/*" ( [^*] | "*"+ [^/*])* "*"+ "/" * Lösung 4 COMMENT = "/*" ~"*/" * Lösung aus JFlex Doku: TraditionalComment = "/*" [^*] ~"*/" | "/*" "*"+ "/" TraditionalComment is the expression that matches the string "/*" followed by a character that is not a *, followed by anything that does not contain, but ends in "*/". As this would not match comments like /****/, we add "/*" followed by an arbitrary number (at least one) of "*" followed by the closing "/". This is not the only, but one of the simpler expressions matching non-nesting Java comments. It is tempting to just write something like the expression "/*" .* "*/", but this would match more than we want. It would for instance match the whole of /* */ x = 0; /* */, instead of two comments and four real tokens. See DocumentationComment and CommentContent for an alternative. * Probleme mit Buffergröße? - Nein, JFlex vergrößert bei Bedarf den Buffer - Alternativlösung (1) "/*" { yybegin(LONGCOMMENT); }{ "*/" { yybegin(YYINITIAL); } .|\n { } } * End-Of-Line LINECOMMENT == "//" ~{NEWLINE} + c) Zeilen-/ Spaltennummern JFlex Direktiven: %line %column Token entsprechend erweitern und Werte übergeben: "false" { return new Token(yyline, yycolumn, Token.Type.FALSE); } * Verbesserte Lösung (keine Gruppe) Definiere neue Methoden im Scanner: %{ private Token token(Token.Type type) { return new Token(yyline, yycolumn, Token.Type, null); } private Token token(Token.Type type, Object value) { return new Token(yyline, yycolumn, Token.Type, value); } %} "false" { return token(Token.Type.FALSE); } + Hauptprogramm * Triviale Lösung %debug