Tworzenie skryptowego języka SWX na Node.js: architektura i implementacja
SWX to skryptowy język oparty na Node.js, realizujący pełny cykl przetwarzania kodu: od analizy leksykalnej do wykonania. Proces obejmuje lekser, parser i interpreter.
Kod źródłowy → [Lekser] → Tokeny → [Parser] → AST → [Interpreter] → Wynik
Lekser dzieli kod na tokeny, uwzględniając niestandardowe operatory, takie jak >~ dla porównania i =? dla równości. Parser buduje AST, interpreter przegląda drzewo i wykonuje węzły.
Lekser: tokenizacja kodu
Lekser (lexer.js) przekształca ciągi znaków w sekwencję tokenów. Przykład:
swx x = 42
Staje się: KEYWORD(swx) IDENT(x) ASSIGN(=) NUMBER(42).
Przetwarzanie wieloznakowych operatorów wymaga priorytetów: >= jest rozpoznawany jako całość. Tryby kontekstowe rozwiązują konflikty z identyfikatorami w generatorze HTML.
Parser i AST
Parser (parser.js) używa rekurencyjnego schodzenia do budowania AST z uwzględnieniem priorytetów operatorów. Przykład warunku:
swx x = 10
sw x >~ 5 {
wx "więcej niż pięć"
}
AST:
{
"type": "IfStatement",
"condition": {
"type": "BinaryExpression",
"operator": ">=",
"left": { "type": "Identifier", "name": "x" },
"right": { "type": "NumberLiteral", "value": 5 }
},
"body": [
{
"type": "PrintStatement",
"value": { "type": "StringLiteral", "value": "więcej niż pięć" }
}
]
}
Priorytety zapewniają poprawność: 2 + 3 4 jest obliczane jako 2 + (3 4).
Interpreter: wykonywanie AST
Interpreter typu tree-walking (interpreter.js) implementuje obsługę węzłów:
IfStatement: ocena warunku i wybór gałęzi.ForLoop: iteracje po liczniku.FunctionDeclaration: przechowywanie w tablicy symboli.BinaryExpression: arytmetyka i logika.
Składnia i konstrukcje
SWX używa unikalnej składni:
Zmienne i wyjście
swx name = "SlywerX"
swx age = 20
wx "Witaj, {name}! Masz {age} lat."
Warunki i pętle
swdla if zdrjako else-if/else.xs 5 { ... }— pętla N razy.xw item in arr { ... }— foreach.xl condition { ... }— while z limitem 1 mln iteracji.
Funkcje i pattern matching
sx add(a, b = 0) => {
ws a + b
}
match status {
case 200 => { wx "OK" }
case 404 => { wx "Nie znaleziono" }
default => { wx "Nieznane" }
}
Operator pipe |> łączy funkcje: "hello" |> upper.
Kryptografia
Moduł #x integruje Node.js crypto:
swx hash = #x.sha256("hello")
wx hash // 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
swx encrypted = #x.aes_enc("dane tajne", "mykey")
swx decrypted = #x.aes_dec(encrypted, "mykey")
swx keys = #x.rsa_keys(2048)
swx signature = #x.rsa_sign("data", keys.private)
wx #x.rsa_verify("data", signature, keys.public) // true
Renderowanie HTML
DSL sx> generuje HTML z CSS:
sx> "output/index.html" {
@style {
body >> bg(#030810) color(#fff) font(Courier New, monospace)
h1 >> color(#00e5ff) size(24px) bold uppercase
.btn >> bg(#00e5ff) color(#000) pad(10px 20px) pointer
}
@body {
div.card >> {
h1 >> "Witaj od SWX"
button.btn >> (onclick: "alert('działa')") { "Kliknij" }
}
}
}
Obsługuje zagnieżdżanie i atrybuty.
Trudności implementacji
- Priorytety w parserze: Rekurencyjne schodzenie z parsowaniem Pratt.
- Konflikty leksera: Kontekst dla
*~i CSS. - Pętle while: Ochrona przed zawieszeniami limitem iteracji.
- Biblioteka standardowa: Testowanie na niestabilnym interpreterze.
Co ważne
- Pełny stos: lekser, parser, interpreter na Node.js.
- Niestandardowa składnia z pipe, pattern matching i modułem kryptograficznym.
- HTML-DSL do generowania znaczników.
- Zabezpieczenia przed nieskończonymi pętlami i konfliktami leksykalnymi.
- Wersja 7.0.0 z RSA i AES.
— Editorial Team
Brak komentarzy.