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).
// Einzeiliger Kommentar – bis zum Zeilenende
/* Mehrzeiliger Kommentar
Nicht verschachtelbar: /* kein weiterer /* */ hier */
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) |
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
| 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 |
| Format | Beispiel | Typ |
|---|---|---|
| Dezimal (Standard) | 3.14, -0.5, 1.0 | f64 |
| Mit Suffix | 3.14f32, 0.0f32 | f32 |
| 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 |
| Sequenz | Bedeutung |
|---|---|
\n | Zeilenumbruch (LF) |
\t | Tabulator |
\r | Wagenrücklauf (CR) |
\\ | Backslash |
\„ | Anführungszeichen |
\0 | Null-Byte (String-Terminator) |
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 |
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)
:=.pub vor der Speicherklasse macht die Variable aus anderen Units sichtbar: pub var x: int64 := 0;| 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*) |
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.
Das ?-Suffix markiert einen Typ als nullable (kann nil sein):
var name: pchar? := GetOptionalName(); // darf nil sein
var node: BSTNode? := FindNode(key);
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.
| 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– |
| 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==.
| 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.
| 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 |
| 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 |
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 (Bedingung) {
// ...
}
// Bounded – garantierte Terminierung
while (Bedingung) limit(Konstante) {
// ...
}
// 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 {
// Körper wird mindestens einmal ausgeführt
} until (Abbruchbedingung);
// Mit Bounded-Limit
repeat {
// ...
} until (Bedingung) limit(Konstante);
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 (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.
fn FunktionsName(param1: Typ1, param2: Typ2): RückgabeTyp {
// Körper
return Wert;
}
return werden weggelassen (implizit void).(Typ1, Typ2).pub voranstellen.
// 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";
}
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
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.lyx → unit my_module;).import macht alle pub-Symbole der Ziel-Unit sichtbar.std.io, std.math, std.string, std.alloc, std.result, std.error, …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;
}
};
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 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 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();
}
}
// 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();
}
Attribute beginnen mit @ und stehen unmittelbar vor dem annotierten Element (Unit, Funktion, Variable).
| Attribut | Ziel | Beschreibung |
|---|---|---|
@flight_crit | Unit, Fn | Strikte Luftfahrt-Regeln: kein Heap, keine unsafe-Blöcke |
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: