Jak analizować ciąg znaków w czasie kompilacji w Nimrod?
Iść przezdruga część tutoriala Nimroda Dotarłem do części, w której wyjaśniono makra. Dokumentacja mówi, że działają w czasie kompilacji, więc pomyślałem, że mogę zrobić parsowanie łańcuchów, aby stworzyć sobie język specyficzny dla domeny. Nie ma jednak przykładów, jak to zrobićprzykład makra debugowania nie wyświetla, jak radzi sobie z parametrem ciągu.
Chcę przekonwertować kod, taki jak:
instantiate("""
height,f,132.4
weight,f,75.0
age,i,25
""")
… W coś, co chciałbym napisać ręcznie:
var height: float = 132.4
var weight: float = 75.0
var age: int = 25
Oczywiście ten przykład nie jest zbyt przydatny, ale chcę spojrzeć na coś prostego (dzielenie multilinii / przecinka, a następnie transformację), co może pomóc mi zaimplementować coś bardziej złożonego.
Moim problemem jest to, w jaki sposób makro uzyskuje ciąg wejściowy, analizuje go (w czasie kompilacji!) I jaki rodzaj kodu można uruchomić w czasie kompilacji (czy to tylko podzbiór języka? Czy mogę używać makr / kodu z innych importowane moduły)?
EDYTOWAĆ: Na podstawie odpowiedzi znajduje się możliwe rozwiązanie kodu na pytanie:
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