====== 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 **Vergleichs**operator. Der **Zuweisungs**operator 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: [[lyx_-_programmiersprache:pattern-matching|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();
→ [[lyx_-_programmiersprache:funktionen|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.lyx'' → ''unit 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(items: [16]T) {
for i := 0 to 15 do {
items[i].Print();
}
}
===== 10. Generics =====
// Generische Funktion
fn Max(a: T, b: T): T {
if (a > b) { return a; }
return b;
}
// Generischer Struct
type Stack = 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(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 |
| ''@dal(A)''..'@dal(E)'' | Unit, Fn | Design Assurance Level nach DO-178C |
| ''@stack_limit(N)'' | Fn | Hartes Stack-Limit in Bytes; geprüft mit ''--stack-check'' |
| ''@wcet(N)'' | Fn | WCET-Annotation in Nanosekunden |
| ''@redundant'' | Variable | Triple Modular Redundancy (TMR) |
| ''@integrity'' | Unit, Fn | Prüfsummen-Überwachung (''scrubbed'' / ''lockstep'') |
==== Performance & Code-Generierung ====
^ Attribut ^ Ziel ^ Beschreibung ^
| ''@inline'' | Fn | Erzwingt Inlining unabhängig vom Energy-Level |
| ''@no_opt'' | Fn | Deaktiviert alle Optimierungen (Timing, Treiber) |
| ''@parallel'' | Schleife | Signalisiert SIMD-Vektorisierbarkeit |
| ''@energy(1..5)'' | Fn | Steuert Optimierungs-Aggressivität des Backends |
| ''@section("name")'' | Fn, Var | Platziert in benannter ELF-Sektion |
==== Interoperabilität ====
^ Attribut ^ Ziel ^ Beschreibung ^
| ''@extern'' | Fn | Externe C-Funktion (Linkage) |
| ''@variadic'' | Fn | Variadische Argumentliste (C-Stil) |
| ''@export'' | Fn | Exportiert als C-kompatibles Symbol |
| ''@volatile'' | Var | Verhindert Wegoptimieren von Zugriffen (MMIO) |
| ''@packed'' | Struct | Kein Padding – exaktes Hardware-Layout |
| ''@stdcall'' | Fn | Windows-Aufrufkonvention |
==== Mehrere Attribute kombinieren ====
@flight_crit
@dal(B)
@stack_limit(512)
@wcet(10000)
fn ProcessFlightData(val: f64): f64 {
@redundant
var heading: f64 := val;
return Clamp(heading, 0.0, 360.0);
}
===== 12. unsafe-Blöcke =====
''unsafe''-Blöcke heben die Typsicherheits-Garantien für einen begrenzten Bereich auf und erlauben Pointer-Arithmetik und Reinterpret-Casts.
unsafe {
var ptr: ^uint8 := base + offset; // Pointer-Arithmetik
var p32: ^uint32 := ptr as ^uint32; // Reinterpret-Cast
var val := p32^; // Dereferenz berechneter Adresse
}
In Modulen mit ''@dal(A)'' oder ''@dal(B)'' erzeugt ''unsafe'' einen Compiler-Fehler.
===== 13. Sonderzeichen & Strukturregeln =====
^ Zeichen ^ Bedeutung ^
| '';'' | Statement-Terminator (Pflicht am Zeilenende) |
| '':'' | Typ-Trenner in Deklarationen (''name: Typ'') |
| ''{ }'' | Block-Begrenzer für Funktionskörper, Schleifen, Bedingungen |
| ''( )'' | Ausdruck-Gruppierung; Pflicht in ''if'', ''while'', ''match'' |
| ''[ ]'' | Array-Index (''arr[i]'') und Array-Typ (''[N]T'') |
| ''.'' | Memberzugriff (''obj.field'', ''obj.Method()'') |
| ''::'' | Enum-Wert-Zugriff (''Status::Ok'') |
| '','' | Trennzeichen in Parameterlisten und Tupeln |
| ''%%^%%'' | Präfix: Address-of (''%%^x%%''); Postfix: Deref (''%%p^%%''); Infix: XOR (''%%a ^ b%%'') |
| ''@'' | Attribut-Präfix (''@inline'', ''@dal(A)'') |
==== Semikolons ====
Semikolons sind in Lyx **Pflicht** als Statement-Abschluss. Sie können nicht weggelassen werden:
var x: int64 := 42; // ✅
var y: int64 := 10 // ✗ Compiler-Fehler: fehlendes ;
Ausnahme: Nach ''}''-Blöcken (Funktionskörper, if, while) wird kein Semikolon benötigt.
===== 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:**
* [[lyx_-_programmiersprache:datentypen|Datentypen – vollständige Typ-Referenz]]
* [[lyx_-_programmiersprache:erste-schritte|Erste Schritte – Einführung mit Beispielen]]
* [[lyx_-_programmiersprache:pattern-matching|Pattern Matching – match im Detail]]
* [[lyx_-_programmiersprache:oop|OOP – Klassen, Traits, Generics]]
* [[lyx_-_programmiersprache:pointer-inlining|Pointer & Inlining – ^T, unsafe, @inline]]
* [[lyx_-_programmiersprache:attributes-pragmas|Attribute & Pragmas – vollständige @-Referenz]]
* [[lyx_-_programmiersprache:ffi|FFI – @extern, @export, @packed]]