Ninja: Erläuterungen zu Ninja-Spezifikationen

Erstellt am 1. Apr. 2015  ·  9Kommentare  ·  Quelle: ninja-build/ninja

Eine Reihe kleinerer Klarstellungen:

1. Das Ninja-Handbuch erwähnt an einigen Stellen "Whitespace"; was bedeutet das genau? Werden Tabulatoren und/oder Zeilenumbrüche als Leerzeichen betrachtet? (Die Tatsache, dass Ninja agnostisch kodiert, deutet zumindest darauf hin, dass Unicode-Whitespace nicht erlaubt ist.)

Die aktuelle Ninja-Implementierung scheint auf \r und \t einen Fehler zu machen. Es könnte klarer sein, einfach "Leerzeichen" statt "Leerzeichen" zu sagen und die Regel über \r und \t explizit anzugeben.

2. Gibt es Einschränkungen bezüglich zulässiger Variablennamen? Ist "foo$ bar = 3" eine gültige Variablenzuweisung? Sind "${foo bar}" und/oder "${foo$ bar}" gültige Verweise auf diese Variable?

Die Ninja-Implementierung scheint nur Bezeichner wie [a-zA-Z0-9_.-]+ zuzulassen (insbesondere Bezeichner wie "42"), obwohl die Syntax "${foo}" für Bezeichner mit Punkten verwendet werden muss . Dies scheint nirgendwo dokumentiert zu sein.

3. "Wenn eine Zeile weiter als die vorherige eingerückt ist, wird sie als Teil des Gültigkeitsbereichs ihres übergeordneten Elements betrachtet. Wenn sie weniger eingerückt ist als die vorherige, wird der vorherige Gültigkeitsbereich geschlossen."

Es ist nicht klar, was "sein Elternteil" hier bedeutet, IMO.

Auch für diese Eingabe streng interpretiert:

rule foo
    x = 1
    y = 2
  z = 3

die Zeile "y = 2" wird nicht "weiter als die vorherige" eingerückt (dh "x = 1"), daher sollte sie _nicht_ als Teil des Geltungsbereichs ihres übergeordneten Elements betrachtet werden.

In ähnlicher Weise wird die Zeile "z = 3" "weniger als die vorherige" eingerückt, sodass sie "den vorherigen Bereich schließen" sollte.

Soweit ich mir die Ninja-Implementierung ansehe, ist der Umfang der Einrückungen unbedeutend, da es innerhalb einer Datei keinen verschachtelten Bereich gibt: Jede eingerückte Zuweisung wird einfach der letzten nicht eingerückten Zeile zugeordnet.

4. Es scheint, dass die Anzahl der Leerzeichen auf der rechten Seite einer Zuweisungsanweisung von Bedeutung ist, aber dies wird nirgendwo erwähnt, was ich sagen kann.

5. Kommentare scheinen nur als eigenständige Zeilen zu funktionieren, obwohl ich intuitiv erwartet hätte, dass sie sich wie Shell-Kommentare verhalten. Vermutlich erwähnenswert.

6. Die Spezifikation sagt: "Die vollständige Suchreihenfolge für eine in einem Build-Block erweiterte Variable (oder die Regel wird verwendet) ist: [...] 2. Build-Level-Variablen aus dem Build-Block."

Aber die aktuelle Implementierung führt angesichts dieser build.ninja "echo 1 2 4" aus:

rule echo
    command = echo $args
args = 1
args = $args 2
build hello: echo
    args = $args 3
    args = $args 4

7. Die aktuelle Implementierung lehnt undefinierte Escape-Sequenzen wie "$!" ab; scheint es wert zu dokumentieren, dass andere Verwendungen von $ ungültig sind.

8. Es gibt keine Escape-Sequenz für das Literal "|" Zeichen, obwohl dies ein ungewöhnliches Zeichen für Dateinamen ist.

Hilfreichster Kommentar

Ich denke, die Implementierung von Ninja ist die definitive Antwort auf die meisten Fragen, aber auch, dass wir die Implementierung von Ninja dort ändern können, wo es keinen Sinn macht.

Sie könnten also in Erwägung ziehen, das Tab-Verbot aufzuheben, denn das Erzwingen eines bestimmten Formatierungsstils ist nur eine Wiederholung von Makes Fehler.

Der Lexer sollte nur dann einen Fehler auslösen, wenn Tabs und Leerzeichen in derselben Datei gemischt werden, was (natürlich) verboten sein sollte. Die erste eingerückte Zeile könnte den erwarteten Einzug für den Rest der Datei festlegen.

Alle 9 Kommentare

Vielleicht ist es besser, dies in die Mailingliste aufzunehmen oder separate Fehler zu den Problemen einzureichen, die Sie speziell beheben möchten. :) Sachen wie das Platzieren von #5 in die Dokumente scheinen eine einfache Pull-Anfrage zu sein.

Bei vielen dieser Eckfälle habe ich es bewusst ungesagt gelassen, weil ich mir nicht ganz sicher war, was die Antwort sein sollte und ich die Umsetzung nicht anbinden wollte, noch halte ich es für wirklich sinnvoll, ein Handbuch mit 20% mehr zu haben Text, der jede letzte Ecke dokumentiert. Ich denke, die Implementierung von Ninja ist die definitive Antwort auf die meisten Fragen, aber auch, dass wir die Implementierung von Ninja dort ändern können, wo es keinen Sinn macht. (Ich denke, die Fehlermeldung, wenn Sie ein "\r" einfügen, erwähnt, dass wir Dinge reparieren könnten, um es möglich zu machen, wenn es Sie wirklich interessiert.) Ich weiß, dass diese Mehrdeutigkeit Probleme verursachen könnte, wenn wir das Verhalten zwischen den Versionen ändern, aber in der Praxis war dies nie der Fall ein Problem.

Zu 3, ursprünglich hatte ich mir mehrere verschachtelte Einrückungsbereiche vorgestellt (wie Haskell "where" -Klauseln), und dann war es nie nützlich. Ich stimme zu, dass die Dokumente alle Erwähnungen von übergeordneten Elementen entfernen und auf "eingerückt oder nicht" vereinfachen könnten.

Zu 4, könnten Sie das genauer ausführen?

Zu 7 und 8, siehe diesen aktuellen Thread: https://groups.google.com/forum/#!topic/ninja -build/UVYk9RhCE4M

Für Element 4 haben diese beiden Builds das gleiche Verhalten:

build a.out: link foo.o bar.o
build a.out: link foo.o  bar.o

aber diese beiden Regeln haben ein unterschiedliches Verhalten:

rule hello_one_space_world
    command = echo "hello world"
rule hello_two_space_world
    command = echo "hello  world"

Ich verstehe warum, aber ich denke, es ist nicht sehr offensichtlich aus dem Handbuch.

Kontext: Meine erste Idee zum Schreiben eines Ninja-Parsers bestand darin, den Wertteil von "var = value" genauso zu behandeln wie eine Liste von Pfaden (dh eine Folge von durch Leerzeichen getrennten Token) und dann würde ich sie einfach mit a wieder verbinden Platz später, aber das ist eigentlich falsch. (Natürlich muss ich "Wert"-Token sowieso wegen : und |-Zeichen auch separat lexieren, also verfolge ich jetzt nur, ob das letzte Token ein "=" war.)

fwiw, ich habe vor einiger Zeit eine formale (PEG) Grammatik für Ninja-Dateien geschrieben, die ich mit den Ninja-Dokumenten zusammenführen wollte, bin aber nie dazu gekommen. Ich denke, es würde die meisten deiner Fragen beantworten...

https://github.com/dpranke/glop/blob/master/test_grammars/ninja.pymeta

Ja auch diese sind unterschiedlich:

command = echo foo$
  bar
command = echo foo $
  bar

Ich stimme zu, dass der beste Weg, dies zu behandeln, darin besteht, dass = einen Abschnitt mit spezieller Lexik beginnt (ähnlich wie " einen Abschnitt mit spezieller Lexik in C beginnt).

dpranke: Danke, das ist hilfreich. (Ich stelle jedoch eine Handvoll Diskrepanzen fest; ist es sinnvoll, sie irgendwo aufzuschreiben?)

Das macht mir auch klar, dass Sie "$\n" nicht verwenden können, um Bezeichner (z. B. Regel- und Variablennamen) zu umschließen dürfen). Es scheint, als ob all die Sonderfälle die traditionelle Lexer + Parser-Generator-Lösung für eine so einfache Grammatik unpraktisch machen. PEG scheint hier schöner zu sein.

Am Mittwoch, 1. April 2015 um 17:38 Uhr, Matthew Dempsky [email protected]
schrieb:

dpranke: Danke, das ist hilfreich. (Ich stelle eine Handvoll Diskrepanzen fest
obwohl; ist es sinnvoll, sie irgendwo aufzuschreiben?)

Ja, wenn es Unstimmigkeiten gibt, ist mein Python-Ninja-Klon wahrscheinlich
buggy und ich würde das gerne beheben :). Wir sollten auch die Grammatik in die
Ninja-Dokumente.

In der Implementierung gibt es zwei Lexer: den einen zum Lesen von Token (der $ nicht versteht) und den anderen zum Lesen von Bezeichnern und Variablenwerten (der $ versteht). Leider bedeutet dies, wie Sie feststellen, dass das Lexing vom Parsen abhängig ist.

Ich denke, die Implementierung von Ninja ist die definitive Antwort auf die meisten Fragen, aber auch, dass wir die Implementierung von Ninja dort ändern können, wo es keinen Sinn macht.

Sie könnten also in Erwägung ziehen, das Tab-Verbot aufzuheben, denn das Erzwingen eines bestimmten Formatierungsstils ist nur eine Wiederholung von Makes Fehler.

Der Lexer sollte nur dann einen Fehler auslösen, wenn Tabs und Leerzeichen in derselben Datei gemischt werden, was (natürlich) verboten sein sollte. Die erste eingerückte Zeile könnte den erwarteten Einzug für den Rest der Datei festlegen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen