Wie parse ich einen String zur Kompilierungszeit in Nimrod?

Durchgehender zweite Teil von Nimrods Tutorial Ich habe den Teil erreicht, in dem Makros erklärt werden. In der Dokumentation heißt es, dass sie zur Kompilierungszeit ausgeführt werden. Daher dachte ich, ich könnte einige Zeichenfolgen analysieren, um mir eine domänenspezifische Sprache zu erstellen. Es gibt jedoch keine Beispiele dafür, dieBeispiel für ein Debug-Makro zeigt nicht an, wie man mit einem String-Parameter umgeht.

Ich möchte Code wie folgt konvertieren:

instantiate("""
    height,f,132.4
    weight,f,75.0
    age,i,25
    """)

... in etwas, was ich gerne von Hand schreiben würde:

var height: float = 132.4
var weight: float = 75.0
var age: int = 25

Offensichtlich ist dieses Beispiel nicht sehr nützlich, aber ich möchte etwas Einfaches betrachten (mehrzeilige / Komma-Aufteilung, dann Transformation), das mir helfen könnte, etwas komplexeres zu implementieren.

Hier geht es darum, wie das Makro die Eingabezeichenfolge abruft, sie analysiert (zur Kompilierungszeit!) Und welche Art von Code zur Kompilierungszeit ausgeführt werden kann (ist es nur eine Teilmenge einer Sprache? Kann ich Makros / Code von anderen verwenden? importierte Module)?

BEARBEITEN: Basierend auf der Antwort ist hier eine mögliche Codelösung für die Frage:

import macros, strutils

# Helper proc, macro inline lambdas don't seem to compile.
proc cleaner(x: var string) = x = x.strip()

macro declare(s: string): stmt =
  # First split all the input into separate lines.
  var
    rawLines = split(s.strVal, {char(0x0A), char(0x0D)})
    buf = ""

  for rawLine in rawLines:
    # Split the input line into three columns, stripped, and parse.
    var chunks = split(rawLine, ',')
    map(chunks, cleaner)

    if chunks.len != 3:
      error("Declare macro syntax is 3 comma separated values:\n" &
        "Got: '" & rawLine & "'")

    # Add the statement, preppending a block if the buffer is empty.
    if buf.len < 1: buf = "var\n"
    buf &= "  " & chunks[0] & ": "

    # Parse the input type, which is an abbreviation.
    case chunks[1]
    of "i": buf &= "int = "
    of "f": buf &= "float = "
    else: error("Unexpected type '" & chunks[1] & "'")
    buf &= chunks[2] & "\n"

  # Finally, check if we did add any variable!
  if buf.len > 0:
    result = parseStmt(buf)
  else:
    error("Didn't find any input values!")

declare("""
x, i, 314
y, f, 3.14
""")
echo x
echo y

Antworten auf die Frage(1)

Ihre Antwort auf die Frage