Seite 1 von 2

Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 20:49
von darktrym
Angeregt durch das Video von sma wollte ich einen Converter basteln der mir das Portieren von Pascal Code erleichert.
Mein Problem ist gleich am Anfang beim zerlegen in die Token.
Dafür wird ein reg. Ausdruck verwendet.
Nun steh ich vor den Problem wie ich Kommentare und Strings handle als ganzes.
Als Beispiel, Pascal kennt (* *) und { } als Kommentar, FreePascal/Delphi erlaubt noch //.
Nun sollen darin keine weiteren Token erkannt werden, was bei mir natürlich kollidiert mit den anderen Regeln wie für Zahlen etc.
Wie stelle ich nun das am besten an? Mein Ansatz[1] funktioniert so nat. nicht, bin auch nicht sonderlich geübt in RegEx.

[1]

Code: Alles auswählen

TOKENS = re.compile(r"\(\*.*?\*\)|\d+")

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 21:21
von BlackJack
@darktrym: *Das* Video vom sma? Ein Link wäre vielleicht nicht schlecht. ;-)

Denn so ohne Kontext sehe ich nicht warum das „natürlich” nicht funktioniert. Der Text '42 (* foo 23 *) 4711' hätte zumindest drei Matches mit dem Ausdruck wobei die 23 in dem Kommentar nicht von dem \d+ erfasst wird.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 21:47
von darktrym
Habs ergänzt, nun sollte klar sein wovon ich sprach.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 22:03
von BlackJack
@darktrym: Nicht wirklich. Was ist denn das konkrete Problem? Zeig doch mal eine Eingabe und die dazugehörige Ausgabe oder Fehlermeldung und beschreibe was nicht wie gewünscht funktioniert. Wie schon gesagt, den ”Ausdruck” '42 (* foo 23 *) 4711' kann man damit wunderbar aufteilen.

Da Pascal nicht zeilenorientiert ist wie der BASIC-Dialekt in sma's Interpreter, kann man den Quelltext natürlich nicht zeilenweise verarbeiten wenn man Kommentare über mehrere Zeilen erkennen will und man muss auch das Flag mitgeben, dass der '.' auch auf '\n' zutreffen kann. Und das MULTILINE-Flag für '//'-Kommentare um das Zeilenende mit '$' erkennen zu können. Ist das das Problem?

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 22:31
von darktrym
Ich glaub, das hilft weiter. Danke.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Dienstag 11. März 2014, 22:33
von diesch
Reguläre Ausdrücke sind für so was genauso wenig geeignet wie für das Parsen von HTML oder XML.

Nimm dir eine richtige Parser-Bibliothek, wie z.B. PyParsing, oder eine Tokenizer/Parsergenerator-Kombination (lex/yacc), wie z.B. PLY

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 08:59
von BlackJack
Zumindest für den Lexer verwendet man üblicherweise schon reguläre Ausdrücke. Ob man mehr braucht, hängt davon ab ob man wirklich die Programmstruktur für die Weiterverarbeitung benötigt, oder ob eine Strom von Tokens ausreicht.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 13:56
von diesch
Verschachtelte Kommentare oder Kommentare, die String-Literale mit Kommentar-Ende-Zeichen enthalten, sind mit echten regulären Ausdrücken nicht zu parsen, mit den perl-artigen Erweiterungen in Python müsste das gehen, aber schön oder einfach ist das eher nicht.

Kommentare zu erkennen ist daher Sache des Parsers, nicht des Lexers.

Man kann sich natürlich auch selbst einen Kellerautomat bauen, mit dem man die Tokens verarbeitet. Aber mit den richtigen Werkzeugen kommt man schneller zu übersichtlichem, robustem Code.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 14:39
von darktrym
Die Zerlegung der Token funktioniert erstmal muss aber trotzdem sukzessiv erweitert werden. Die Grammatik ist ein wenig komplexer als Basic.
Vielleicht kennt jemand eine gute Seite zur Übersicht.

Eine Frage zum Abschluss, zur Überprüfung ob alles wichtige in Token aufgeteilt wurde, hätte ich gern eine Möglichkeit der Überprüfung. Praktischerweise verliert man ja alle Formatierungszeichen und Whitespaces. Für die Verarbeitung toll, zur Kontrolle bescheiden.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 15:08
von BlackJack
@darktrym: Schau Dir FreePascal an, notfalls die Quellen für deren Parser. Und verwende wie diesch schon sagte eine Parserbibliothek.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 15:36
von darktrym
@diesch: Kannst mal ein Beispiel nennen, das ich testen kann. Kann mir so recht schwer vorstellen, warum das schief gehen sollte.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 15:53
von BlackJack
@darktrym: '(* (* test *) *)'. Das ist aber kein Standardpascal und weder TurboPascal noch Delphi verarbeiten das. FreePascal erlaubt das, wenn man nicht im TP- oder Delphi-Modus übersetzt, gibt aber eine Warnung aus.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 20:24
von darktrym
Rein aus Interesse(nicht auf Pascal bezogen) wenn sowas wie "\"" in C hätte, das begreift doch kein reg. Ausdruck.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 20:41
von Sirius3
@diesch: ich hoffe mal, dass es keine Sprache gibt, in denen Stringliterale eine besondere Rolle innerhalb von Kommentaren spielen, weil das auch jeden Parser vor unlösbare Probleme stellt.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Mittwoch 12. März 2014, 20:55
von BlackJack
@darktrym: Natürlich kann man da einen regulären Ausdruck für schreiben. Da muss man noch nicht einmal \" besonders berücksichtigen, sondern kann ganz allgemein Escape-Sequenzen berücksichtigen: r'"(\\.|[^"])*"'. Hier jetzt mal nur für Sequenzen die nur aus einem Zeichen bestehen.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Donnerstag 13. März 2014, 09:00
von darktrym
Sirius3 hat geschrieben:@diesch: ich hoffe mal, dass es keine Sprache gibt, in denen Stringliterale eine besondere Rolle innerhalb von Kommentaren spielen, weil das auch jeden Parser vor unlösbare Probleme stellt.
Pascal verfolgt zum. so ein Konzept namens Compilerdirektiven, dass sein Kommentarblock evtl. umfunktioniert wenn ein Dollarzeichen am Anfang gefunden wurde. Was noch erwähnenswert ist, irgendjemand dachte es ist cool sowas zu erlauben {Kommentar*).

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Donnerstag 13. März 2014, 13:19
von darktrym
Wie formuliere ich denn richtig den Kommentar als Regel, mein Ansatz scheint jedenfalls nicht ganz richtig zu sein.
r"[\{|(\(\*)].*?[\}|(\*\))]
Testdaten:

Code: Alles auswählen

(* 2047 jjkhAS asd
 * +asasdasda
 *)
var s:string;
{QUARK}
(*Test}
begin 
    writeln('HALLO');
    var a: int;
    a:=234;
    a := 1+2*3+(3*3);
    ^a := 2;
    if a=3 then begin end;
end.
Ergebnis, erwischt nich nur Kommentare:

Code: Alles auswählen

['(*', '* +asasdasda\n *', ')\nvar s:string;\n{QUARK}', '(*', "('HALLO')", '*3+(', '*3)']
PS: Das hiesige Formatierungsskript machts übrigens auch falsch.
PPS: Ich weiß das oben ist nicht pascal-konform.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Donnerstag 13. März 2014, 13:28
von Sirius3
@darktrym: Eckige Klammern definieren in regulären Ausdrücken Mengen.
Was Du willst, ist "(?:{|\(\*).*?(?:}|\*\))".

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Donnerstag 13. März 2014, 13:31
von BlackJack
@darktrym: Innerhalb von eckigen Klammern gelten andere Regeln. Die meisten Sonderzeichen verlieren ihre besondere Bedeutung, dafür gibt es dort Zeichen mit besonderer oder anderer Bedeutung als ausserhalb. ^ ist zum Beispiel Negation statt Anfang der Zeichenkette, - hat die Bedeutung „bis” wenn es zwischen zwei Zeichen steht, | und die runden Klammern sind einfach nur | und runde Klammern und keine Alternative oder Gruppe.

Edit: Zu *dem* richtigen Ausdruck für Kommentare muss man wohl auch immer dazu angeben wie Kommentare eigentlich definiert sind, denn das scheint sich ja von Compiler zu Compiler zu unterscheiden, beziehungsweise von Optionen/Direktiven abhängig zu sein.

Re: Zerlegen in Token, RegEx Ausdruck für Pascal

Verfasst: Donnerstag 13. März 2014, 13:50
von darktrym
Es gibt für Pascal eine ISO-Norm.

Da steht drin:
Where a commentary shall be any sequence of characters and separations of lines, containing neither } nor *), the construct

( '{' | '(*' ) commentary ( '*)' | '}' )

shall be a comment if neither the { nor the (* occurs within a character-string or within a commentary.

NOTES

A comment may thus commence with { and end with *), or commence with (* and end with }.
The sequence (*) cannot occur in a commentary even though the sequence {) can.