Lyx – Syntax-Referenz

Diese Seite ist die vollständige Syntax-Referenz für Lyx. Sie beschreibt alle lexikalischen Regeln, Operatoren, Kontrollstrukturen und Deklarationsformen. Für konzeptuelle Erläuterungen und Code-Beispiele zu einzelnen Themen existieren eigene Unterseiten (verlinkt am Ende jedes Abschnitts).

1. Lexikalische Regeln

Kommentare

// Einzeiliger Kommentar – bis zum Zeilenende

/* Mehrzeiliger Kommentar
   Nicht verschachtelbar: /* kein weiterer /* */ hier */

Identifier

Bezeichner folgen dem Muster [A-Za-z_][A-Za-z0-9_]*. Lyx ist case-sensitive: MyVar, myVar und MYVAR sind drei verschiedene Bezeichner.

Gültig Ungültig
counter, _tmp, Vec2 2fast (beginnt mit Zahl)
MAX_SPEED, isReady my-var (Bindestrich)
x64, uart0 for (Schlüsselwort)

Schlüsselwörter

Reservierte Wörter, die nicht als Identifier verwendet werden dürfen:

and        as         break      case       class      co
con        continue   default    dispose    do         downto
else       enum       extends    false      fn         for
if         impl       import     is         let        limit
match      mod        new        nil        not        or
override   pub        repeat     return     self       struct
super      to         trait      true       type       unit
unsafe     until      var        virtual    when       while

2. Literale

Integer-Literale

Format Beispiel Typ
Dezimal (Standard) 42, -7 int64
Dezimal mit Suffix 42i8, 255u8, 1000i32 wie Suffix
Hexadezimal 0xFF, 0x3FF44000 int64 (oder mit Suffix)
Hexadezimal mit Suffix 0xFFu8, 0x80u32 wie Suffix

Integer-Suffixe:

Suffix Typ Suffix Typ
(keiner) int64 u8 uint8
i8 int8 u16 uint16
i16 int16 u32 uint32
i32 int32 u64 uint64

Float-Literale

Format Beispiel Typ
Dezimal (Standard) 3.14, -0.5, 1.0 f64
Mit Suffix 3.14f32, 0.0f32 f32

Sonstige Literale

Typ Literal Anmerkung
bool true, false
qbool 0.5q, 0.0q, 1.0q Wahrscheinlichkeitswert 0.0–1.0
char 'a', '\n' ASCII, ein Zeichen
pchar „Hallo\n“ Nullterminierter String, Typ pchar
nil nil Null-Pointer für jeden Pointer-Typ

String-Escape-Sequenzen

Sequenz Bedeutung
\n Zeilenumbruch (LF)
\t Tabulator
\r Wagenrücklauf (CR)
\\ Backslash
\„ Anführungszeichen
\0 Null-Byte (String-Terminator)

3. Speicherklassen & Variablen

Jede Variable in Lyx trägt eine explizite Speicherklasse. Die Klasse bestimmt Mutabilität und Lebenszeit.

Keyword Mutabilität Speicherort Beschreibung
var Veränderlich Stack / Data-Segment Standard-Variable; Wert kann jederzeit geändert werden
let Einmalig Stack / Data-Segment Wert wird einmalig zur Laufzeit gesetzt, danach read-only
co Read-only Stack Schreibgeschützter Stack-Slot; ähnlich wie let, aber ohne Heap-Zugriff
con Compile-Zeit Code (Immediate) Compile-Zeit-Konstante; wird direkt in den Maschinencode eingebettet

Syntax

var counter: int64 := 0;           // Typ explizit, Wert zugewiesen
var name := "Lyx";                 // Typ inferiert: pchar
let max_val: int64 := ReadConfig(); // Einmalige Zuweisung
co PI: f64 := 3.14159265358979;    // Stack-Konstante
con MAX_BUFFER := 4096;            // Compile-Zeit-Konstante (int64 inferiert)

  • Der Zuweisungsoperator ist immer :=.
  • Typangabe ist optional wenn der Typ aus dem Initialisierer eindeutig inferierbar ist.
  • pub vor der Speicherklasse macht die Variable aus anderen Units sichtbar: pub var x: int64 := 0;

4. Typsystem

Primitive Typen

Typ Bits Wertebereich
int8 8 −128 … 127
int16 16 −32 768 … 32 767
int32 32 −2 147 483 648 … 2 147 483 647
int64 / int 64 −9 223 372 036 854 775 808 … 9 223 372 036 854 775 807
uint8 8 0 … 255
uint16 16 0 … 65 535
uint32 32 0 … 4 294 967 295
uint64 64 0 … 18 446 744 073 709 551 615
isize Plattform Pointer-Größe (signiert)
usize Plattform Pointer-Größe (unsigniert); Standard für Indizes
f32 32 IEEE 754 Single
f64 64 IEEE 754 Double
bool 1 (8 im Speicher) true, false
qbool 64 (f64) Probabilistischer Typ; 0.0 … 1.0
char 8 Ein ASCII-Zeichen
pchar 64 (Pointer) Nullterminierter String (char*)

Pointer-Typen

var p:  ^int64   := ^x;      // Pointer auf int64 (Address-of: ^x)
var pp: ^(^int64) := ^p;     // Pointer auf Pointer auf int64
var v:  ^uint8   := nil;     // Null-Pointer

p^  := 42;                   // Dereferenz (Schreiben)
PrintInt(p^);                 // Dereferenz (Lesen)

Alle Pointer sind intern 64-Bit-Integer. Der Cast ptr as int64 und addr as ^T ist explizit möglich.

Nullable Typen

Das ?-Suffix markiert einen Typ als nullable (kann nil sein):

var name: pchar?  := GetOptionalName();    // darf nil sein
var node: BSTNode? := FindNode(key);

Range-Typen

type Altitude = int64 range -1000..60000;
type Speed    = int64 range 0..300;

Compile-Zeit: Literale außerhalb des Bereichs → Fehler. Laufzeit: Nicht-konstante Zuweisung → panic.

5. Operatoren

Arithmetik

Operator Operation Beispiel
+ Addition a + b
- Subtraktion / Negation a - b, -x
* Multiplikation a * b
/ Division (ganzzahlig bei int) a / b
mod Modulo (Rest) a mod b
++ Inkrement (postfix) i++
Dekrement (postfix) i–

Vergleich

Operator Bedeutung
= Gleich
!= Ungleich
< Kleiner als
> Größer als
Kleiner oder gleich
>= Größer oder gleich
 
Wichtig: In Lyx ist = der Vergleichsoperator. Der Zuweisungsoperator ist :=. Es gibt kein ==.

Logisch & Bitweise

Operator Bedeutung Anwendung
& Logisches / Bitweises AND bool-Ausdrücke und Integer-Maskierung
| Logisches / Bitweises OR bool-Ausdrücke und Integer-Flags
! Logisches NOT Nur auf bool
~ Bitweises NOT (Komplement) Nur auf Integer
^ Bitweises XOR (Infix) a ^ b
« Bitshift links 1 « 3 = 8
» Bitshift rechts 0x80 » 4 = 8
 
Pointer vs. XOR:
Das Zeichen ^ hat je nach Position unterschiedliche Bedeutungen:
Präfix (^x) = Address-of-Operator, Postfix (p^) = Dereferenz, Infix (a ^ b) = Bitweises XOR.

Spezialoperatoren

Operator Name Beschreibung Beispiel
:= Zuweisung Weist einen Wert zu x := 42
|> Pipe Ergebnis links als erstes Argument rechts val |> Abs()
?. Safe Call Memberzugriff nur wenn nicht nil node?.Next
?? Null-Coalesce Fallback wenn nil name ?? „Gast“
as Cast Explizite Typkonvertierung x as f64
is Typ-Test Prüft Laufzeit-Typ obj is Circle
.. Bereich In match-Mustern und Range-Typen 100..199

Operator-Präzedenz (absteigend)

Priorität Operatoren Assoziativität
1 (höchste) Unär: !, ~, -, ^x (Adresse), p^ (Deref) Rechts
2 *, /, mod Links
3 +, - Links
4 <<, » Links
5 & Links
6 ^ (XOR) Links
7 | Links
8 =, !=, <, >, , >= Nicht-assoziativ
9 as, is Links
10 ?. Links
11 ?? Rechts
12 |> Links
13 (niedrigste) := Rechts

6. Kontrollfluss

if / else

if (Bedingung) {
    // ...
} else if (andere_Bedingung) {
    // ...
} else {
    // ...
}

if ist kein Ausdruck – es gibt keinen ternären Operator ?:. Bedingte Werte werden über match oder Hilfsfunktionen ausgedrückt.

while

while (Bedingung) {
    // ...
}

// Bounded – garantierte Terminierung
while (Bedingung) limit(Konstante) {
    // ...
}

for

// Aufwärts (inklusive Grenzen)
for i := Startwert to Endwert do {
    // i läuft von Startwert bis einschließlich Endwert
}

// Abwärts
for i := Endwert downto Startwert do {
    // i läuft von Endwert bis einschließlich Startwert
}

Die Laufvariable wird automatisch inkrementiert / dekrementiert. Ihr Typ wird vom Compiler inferiert. for-Schleifen sind immer bounded – kein limit erforderlich.

repeat-until

repeat {
    // Körper wird mindestens einmal ausgeführt
} until (Abbruchbedingung);

// Mit Bounded-Limit
repeat {
    // ...
} until (Bedingung) limit(Konstante);

break & continue

while (true) {
    if (DoneCondition()) { break; }    // verlässt die innerste Schleife
    if (SkipCondition()) { continue; } // springt zum nächsten Durchlauf
}

break und continue wirken immer auf die innerste umgebende Schleife.

match

match (Ausdruck) {
    case Wert       => Anweisung;
    case A | B      => Anweisung;      // OR-Muster
    case lo..hi     => Anweisung;      // Bereichsmuster
    case X when (Guard) => Anweisung;  // mit Guard-Bedingung
    default         => Anweisung;
}

match kann als Ausdruck verwendet werden (Ergebnis einer Case-Arm-Anweisung). Alle Fälle müssen abgedeckt sein (Exhaustivität). Details: Pattern Matching.

7. Funktionen

Deklaration

fn FunktionsName(param1: Typ1, param2: Typ2): RückgabeTyp {
    // Körper
    return Wert;
}

  • Kein Rückgabewert: Rückgabetyp und return werden weggelassen (implizit void).
  • Mehrere Rückgabewerte: Tupel-Syntax (Typ1, Typ2).
  • Öffentliche Sichtbarkeit: pub voranstellen.

Beispiele

// Einfache Funktion
fn Add(a: int64, b: int64): int64 {
    return a + b;
}

// Keine Rückgabe (void)
fn Log(msg: pchar) {
    PrintStr(msg);
}

// Tupel-Rückgabe (mehrere Werte)
fn Divide(a: int64, b: int64): (int64, bool) {
    if (b = 0) { return (0, false); }
    return (a / b, true);
}

// Öffentlich
pub fn GetVersion(): pchar {
    return "1.0.0";
}

Aufruf

var result := Add(3, 4);

var (quotient, ok) := Divide(10, 3);
if (ok) { PrintInt(quotient); }

// Pipe-Operator: Wert als erstes Argument
var v := -3.14 |> Abs() |> Round();

Funktionen (vertieft) — Tupel-Rückgabe, anonyme Funktionen, Higher-Order Functions, Pipe-Operator

8. Units & Imports

Jede Lyx-Quelldatei beginnt mit einer unit-Deklaration. Sie definiert den Namensraum der Datei.

unit my_module;

import std.io;
import std.math;
import my_project.utils;

  • unit-Name und Dateiname müssen übereinstimmen (my_module.lyxunit my_module;).
  • import macht alle pub-Symbole der Ziel-Unit sichtbar.
  • Standard-Bibliothek: std.io, std.math, std.string, std.alloc, std.result, std.error, …

9. Typdefinitionen

struct

Stack-allozierte Wertetypen. Zuweisung kopiert den gesamten Wert.

type Vec2 = struct {
    x: f64;
    y: f64;

    fn Length(): f64 {
        return Sqrt(self.x * self.x + self.y * self.y);
    }

    fn Scale(factor: f64) {
        self.x := self.x * factor;
        self.y := self.y * factor;
    }
};

class

Heap-allozierte Referenztypen. new erzeugt, dispose gibt frei.

type Animal = class {
    name: pchar;

    fn Create(n: pchar) {
        self.name := n;
    }

    fn Destroy() {
        // Aufräum-Logik
    }

    virtual fn Speak() {
        PrintStr(self.name);
    }
};

type Dog = class extends Animal {
    override fn Speak() {
        PrintStr("Wuff!");
    }
};

var d := new Dog("Bello");
d.Speak();    // "Wuff!"
dispose d;

Schlüsselwörter für Klassen:

Keyword Bedeutung
extends Einfachvererbung
virtual fn Überschreibbare Methode (V-Table-Eintrag)
override fn Überschreibt eine virtuelle Methode
abstract fn Muss in abgeleiteten Klassen implementiert werden
super.Methode() Aufruf der Eltern-Implementierung
self Referenz auf das aktuelle Objekt
new T(args) Heap-Allokation
dispose ptr Heap-Freigabe

enum

enum Richtung { Nord, Sued, Ost, West }

enum StatusCode {
    Ok     = 200,
    NotFound = 404,
    Error  = 500
}

// Zugriff über ::
var d := Richtung::Nord;
var s := StatusCode::Ok;

match über Enums prüft Exhaustivität: Fehlt ein Fall, erzeugt der Compiler einen Fehler.

trait & impl

trait Printable {
    fn Print();
    fn ToString(): pchar;   // muss implementiert werden
}

type Point = struct { x: int64; y: int64; };

impl Printable for Point {
    fn Print() {
        PrintStr(self.ToString());
    }

    fn ToString(): pchar {
        return FormatStr("(%d, %d)", self.x, self.y);
    }
}

Generics mit Trait-Schranken:

fn PrintAll<T: Printable>(items: [16]T) {
    for i := 0 to 15 do {
        items[i].Print();
    }
}

10. Generics

// Generische Funktion
fn Max<T: Comparable>(a: T, b: T): T {
    if (a > b) { return a; }
    return b;
}

// Generischer Struct
type Stack<T> = struct {
    data: [64]T;
    top:  int64;

    fn Push(val: T) {
        self.data[self.top] := val;
        self.top++;
    }

    fn Pop(): T {
        self.top--;
        return self.data[self.top];
    }
};

// Mehrere Schranken mit +
fn Process<T: Printable + Comparable>(val: T) {
    val.Print();
}

11. Attribute & Pragmas

Attribute beginnen mit @ und stehen unmittelbar vor dem annotierten Element (Unit, Funktion, Variable).

Sicherheit & Zertifizierung

Attribut Ziel Beschreibung
@flight_crit Unit, Fn Strikte Luftfahrt-Regeln: kein Heap, keine unsafe-Blöcke

14. Vollständige Grammatik-Übersicht (kompakt)

Program    → (Unit Import* Decl*)?
Unit       → 'unit' Ident ';'
Import     → 'import' QualIdent ';'

Decl       → VarDecl | FnDecl | TypeDecl | TraitDecl | ImplDecl

VarDecl    → Modifier? StorageClass Ident (':' Type)? ':=' Expr ';'
StorageClass → 'var' | 'let' | 'co' | 'con'
Modifier   → 'pub'

FnDecl     → Attr* Modifier? 'fn' Ident GenericParams? '(' Params ')' (':' Type)? Block
Params     → (Ident ':' Type (',' Ident ':' Type)*)?

TypeDecl   → 'type' Ident GenericParams? '=' ('struct' | 'class' ('extends' Ident)?) '{' Member* '}'
EnumDecl   → 'enum' Ident '{' (Ident ('=' IntLit)? (',' Ident ('=' IntLit)?)*)? '}'
TraitDecl  → 'trait' Ident '{' FnSignature* '}'
ImplDecl   → 'impl' Ident 'for' Ident '{' FnDecl* '}'

Block      → '{' Stmt* '}'
Stmt       → VarDecl | ExprStmt | IfStmt | WhileStmt | ForStmt | RepeatStmt
           | MatchStmt | ReturnStmt | BreakStmt | ContinueStmt | UnsafeBlock

IfStmt     → 'if' '(' Expr ')' Block ('else' 'if' '(' Expr ')' Block)* ('else' Block)?
WhileStmt  → 'while' '(' Expr ')' ('limit' '(' IntLit ')')? Block
ForStmt    → 'for' Ident ':=' Expr ('to' | 'downto') Expr 'do' Block
RepeatStmt → 'repeat' Block 'until' '(' Expr ')' ('limit' '(' IntLit ')')? ';'
MatchStmt  → 'match' '(' Expr ')' '{' MatchArm* '}'
MatchArm   → ('case' Pattern ('when' '(' Expr ')')? | 'default') '=>' Stmt ';'

Expr       → ... (vollständige Präzedenz-Hierarchie; siehe Abschnitt 5)

Weiterführende Seiten: