Makros
- Rust-Makros werden verwendet, um Codeduplizierung zu vermeiden und Wiederholungen zu reduzieren.
- Die Satzknoten von
sqleibniz müssen das Node-Trait implementieren, was zu viel Code-Duplizierung führt.
- Mit Makros lassen sich die Definition von Strukturen und die Implementierung des
Node-Traits automatisieren.
Makro zur Vermeidung von Codeduplizierung
- Das Makro definiert Strukturen, fügt Dokumentationskommentare hinzu und implementiert Funktionen, die das
Node-Trait erfüllen.
- Das Makro kann über wiederholte Metavariablen-Definitionen verschiedene Felder hinzufügen.
Tests
- In Rust lässt sich ein Ansatz umsetzen, der den tabellenbasierten Tests in Go ähnelt.
- Mit den Makros
test_group_pass_assert! und test_group_fail! können verschiedene Paare aus Eingaben und erwarteten Ausgaben getestet werden.
Parser-Tests
- Auch im Parser-Modul werden ähnliche Makros verwendet, um die Ergebnisse von SQL-Anweisungen zu testen.
- Zum Testen von
EXPLAIN-SQL-Anweisungen wird die Funktion sql_stmt_prefix verwendet.
Nachteile von Makros
rust-analyzer funktioniert innerhalb von Makros nicht gut, und die Dokumentation ist unzureichend.
Zeichenabgleich
- Mit Rusts
matches!-Makro lassen sich Zeichen einfach vergleichen.
- Es gibt ein Beispiel dafür, zu prüfen, ob ein gegebenes Zeichen eine SQLite-Zahl ist.
Token-Abgleich
- Nachdem der Lexer einen Zeichenstrom in einen Tokenstrom umgewandelt hat, verwendet der Parser diesen, um einen Syntaxbaum zu erzeugen.
- Mit der
match-Anweisung werden Tokentypen erkannt.
Fehleranzeige
- Durch Fehlerbehandlung werden den Nutzern klare Fehlermeldungen bereitgestellt.
Optionale Funktionen
- Mit Rusts
Option-Typ lässt sich prüfen, ob ein Wert vorhanden ist, Bedingungen prüfen oder ein Standardwert bereitstellen.
- Methoden wie
is_some_and, map und map_or verbessern die Lesbarkeit des Codes.
Iteratoren
- Mit Rust-Iteratoren lassen sich Zeichen filtern und gemäß den SQLite-Regeln für das Parsen von Zahlen verarbeiten.
1 Kommentare
Hacker-News-Kommentare
Wegen des Borrow Checkers von Rust und der Schwierigkeiten bei der Speicherverwaltung hatte ich Probleme, Rust zu verwenden. Die funktionalen Programmier(FP)-Elemente von Rust gefielen mir, aber ich entschied mich, nach einer anderen Sprache zu suchen. Ich entdeckte OCaml und war damit zufrieden
Es scheint, als fehle es an Erfahrung mit Rust und Ideen aus der Programmiersprachenforschung. Ich denke, es wäre einfacher, den AST als algebraischen Datentyp zu definieren. Makros funktionieren in den meisten Sprachen unterschiedlich, werden aber hauptsächlich verwendet, um Codeduplizierung zu vermeiden und Wiederholungen zu reduzieren
Der Parser, den ich in Haskell geschrieben habe, ist in Bezug auf Einfachheit und Lesbarkeit hervorragend. Er liest sich fast wie BNF, und es gibt kaum technischen Ballast, sodass man sich auf die eigentliche Grammatik konzentrieren kann
Ich habe Parser mit Ragel, Go, Java, C++, C geschrieben. Einen JSON-Parser in C zu schreiben kann einfacher sein als Rust-Code. Die Parser-Infrastruktur hat sich so weit entwickelt, dass man einen Sättigungspunkt erreicht, an dem man Parser mit eBNF erstellen kann
Ich habe einen eBPF-Disassembler und -Emulator in Rust geschrieben und denke, dass Rust gut für Parsing-Aufgaben geeignet ist. Allerdings fühlt sich die Verwendung von Makros anders an als die Arbeit innerhalb der Sprache selbst
Ich mag Rob Pikes Vortrag über Lexical Scanning in Go. Das ist ein lehrreicher und eleganter Ansatz
Mit einer Parser-Combinator-Bibliothek kann man Hochleistungs-Protokollparser in Embedded-Umgebungen deployen. Mit derselben Bibliothek kann man auch Embedded-Protokollparser schreiben
Als ich in Rust einen vollständigen AST-Parser schrieb, war es schwierig, die Hierarchie konkreter AST-Typen auszudrücken. Ich musste seltsame Typtricks und Makros verwenden
Die sqlite-Syntax zu parsen ist eine schwierige Aufgabe. sqlite ist eine inspirierende Quelle. Railroad-Diagramme sind sehr nützlich, und der Lemon-Parsergenerator erhält nicht genug Anerkennung
Eine Sprache mit algebraischen Datentypen eignet sich gut zum Parsen der sqlite-Syntax. Typescript könnte ebenfalls eine gute Wahl sein. Ich habe eine kurze Einführung darüber geschrieben, wie man Parser in Rust schreibt