"Offside" (einrückungsbasierte) Sprachen analysieren

8

Eine Sprache ist diejenige wo

  

... der Umfang der Deklarationen (ein Block) in dieser Sprache wird durch ihre Einrückung ausgedrückt.

Beispiele für solche Sprachen sind Python, Boo, Nemerle, YAML und einige mehr.

Meine Frage ist also: Wie analysiere ich diese? Wie löse ich Probleme mit Tabs und Leerzeichen auf (sind zwei Tabs oder 8 Leerzeichen äquivalent oder nicht)? Sind Parsergeneratoren von irgendwelcher Hilfe hier oder muss ich Lexer / Parser selbst Hand-Code?

    
Anton Gogolev 01.02.2010, 16:52
quelle

6 Antworten

5

Python hat einen Lexer , der Indent und Dementent Tokens erzeugt, die geschweiften Klammern entsprechen ("{", "}") . Es gibt sogar ein Beispiel auf Stack Overflow mit eine einfache Implementierung eines solchen Lexers.

Für Registerkarten und Leerzeichen hat Python nur eine Codierung Konvention : Verwenden Sie vier Leerzeichen pro Einrückung Niveau. Tabs sind jedoch legale Syntax.

    
Eike 10.08.2010 23:13
quelle
4
  

Wie löse ich Probleme mit Tabs und Leerzeichen auf (sind zwei Tabs oder 8 Leerzeichen äquivalent oder nicht)?

Es hängt davon ab, wie die Einstellungen des Editors aussehen, wenn zwei Registerkarten acht Leerzeichen enthalten.

Die Offside-Regel, wie sie vom Urheber angegeben wird, erwähnt die relative Positionierung zweier aufeinanderfolgender Codezeilen und nicht die absolute Anzahl der Leerzeichen. Hier ist eine nette Lektüre, die Ihnen hilft, (und einige Zitate) besser zu verstehen:

  

"Whitespace ist in Python von Bedeutung   Quellcode. "

     

Nein, nicht allgemein. Nur der   Einzugsebene Ihrer Aussagen   ist signifikant (d. h. der Leerraum bei   ganz links von Ihren Aussagen).   Überall sonst ist Whitespace nicht   signifikant und kann wie Sie verwendet werden   wie in jeder anderen Sprache.   Sie können auch leere Zeilen einfügen   enthalten nichts (oder nur willkürlich   Leerzeichen) überall.

     

Auch die genaue Höhe des Eindrucks   spielt überhaupt keine Rolle, sondern nur die   relative Einrückung von verschachtelten Blöcken   (relativ zueinander). [...]

    
dirkgently 01.02.2010 17:02
quelle
4

Der einfachste Weg, das Problem "Tabs versus Leerzeichen" aufzulösen, besteht darin, Kombinationen von Leerzeichen und Tabulatoren zu verbieten (dies geschieht beispielsweise in F #). Jeder moderne Editor ermöglicht die Umwandlung von Tabs in eine bestimmte Anzahl von Leerzeichen.

Ob Sie Parsergeneratoren aufgeben müssen, wahrscheinlich nicht, aber Sie müssen irgendwo die Identifikation der Abseits hacken. Dies kann ein wenig Kreativität auf Ihrer Seite erfordern. Basierend auf dem Durchsuchen der F # -Quelle sieht es so aus, als ob sie einen post-lexing-Schritt verwenden, um zusätzliche Token zu erstellen, die die sprachfernen Elemente darstellen.

    
kvb 12.02.2010 15:56
quelle
2

Für was es sich lohnt, ist Haskell auch indentationsbasiert und optional {foo; Bar; usw.} für whitespace ist unbequem. Ich schrieb einen einfachen indentation-basierten Parser mit Parsec , es ist beabsichtigt, wie Lisp zu lesen, aber die Einrückung zeigt die Anwendung des Operators an. Klammern können nur in einer Zeile verwendet werden.

%Vor%

Hier wird aaa auf bb angewendet. Was daraus resultiert, ist eine ternäre Funktion. Es wird auf die Argumente cc , e angewendet auf ein Argument und ddd angewendet. Sehen Sie, wie die Anwendung auf Spaltenausrichtung basiert, und nicht auf X-Leerzeichen.

Der Parser könnte wahrscheinlich auch viel einfacher sein.

    
Christopher Done 05.10.2010 08:50
quelle
1

Sie haben mehrere Möglichkeiten w.r.t. Tabs und Leerzeichen: entweder das Mischen von Tabulatoren und Leerzeichen, das Annehmen eines festen Verhältnisses von Tabulatoren zu Leerzeichen oder das Erlauben des Programmierers, sich pro Projekt oder pro Quelldatei zu entscheiden (irgendeine Art von "#pragma tab (4)" -Stil-Anweisung zu) erlauben Tabs und / oder ändern die Anzahl der Räume, die sie darstellen).

Parser Generator wie ANTLR 3 kann leicht damit umgehen; Ich spielte selbst mit einem Beispiel und kompilierte zu seinem C # -Ziel. Der Link in DirkGentys Antwort erklärt den Python-Algorithmus, der übersetzt direkt in Code. Mein Ansatz bestand einfach darin, separate Token für Leerzeichen und Zeilenumbrüche zu definieren und die Funktion "Token ausgeben" zu überschreiben, die vom Lexer verwendet wurde, um zusätzliche Einzugs- / Gedrückt-Token im laufenden Betrieb einzufügen. Dies erwies sich als einfacher zu implementieren als andere Ansätze, die ich gesehen habe, welche die Funktion "get last token" überschreiben, aber beide funktionieren ziemlich gut.

    
El Zorko 18.03.2010 21:32
quelle
0

Ich habe eine Lösung von mir selbst, die ich den Code genau wie Blöcke für den Schachtelbaum analysiere. Für den Teil der Klammern habe ich nur die normale Methode verwendet.

Hier ist dieser Parser: Ссылка

    
jiyinyiyong 10.12.2013 12:29
quelle