diff --git a/Program.cs b/Program.cs index 9f30372..a39a728 100644 --- a/Program.cs +++ b/Program.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; using System.Collections.Generic; +// === ENTRY POINT === class Program { static int Main(string[] args) { if (args.Length < 2) { @@ -31,6 +32,7 @@ public abstract class Stmt:StNode{} public class AssignStmt:Stmt{ public string Target; public Expr Expr; } public class IfStmt:Stmt{ public Expr Cond; public List ThenStmts=new(); public List ElseStmts=new(); } public class WhileStmt:Stmt{ public Expr Cond; public List Body=new(); } +public class ForStmt:Stmt{ public string Var; public Expr Start, End, Step = new IntExpr(1); public List Body=new(); } public abstract class Expr:StNode{} public class IntExpr:Expr{ public int Value; public IntExpr(int v){Value=v;} } @@ -44,6 +46,7 @@ public enum TokType { LT, GT, LE, GE, EQ, NEQ, IF, THEN, ELSE, END_IF, WHILE, DO, END_WHILE, + FOR, TO, BY, END_FOR, PROGRAM, VAR, END_VAR, END_PROGRAM, EOF } @@ -75,6 +78,10 @@ public class StLexer { "WHILE"=>new Token(TokType.WHILE,s), "DO"=>new Token(TokType.DO,s), "END_WHILE"=>new Token(TokType.END_WHILE,s), + "FOR"=>new Token(TokType.FOR,s), + "TO"=>new Token(TokType.TO,s), + "BY"=>new Token(TokType.BY,s), + "END_FOR"=>new Token(TokType.END_FOR,s), _=>new Token(TokType.IDENT,s) }; } @@ -151,6 +158,7 @@ public class StParser { Stmt ParseStmt(){ if(cur.Type==TokType.IF) return ParseIf(); if(cur.Type==TokType.WHILE) return ParseWhile(); + if(cur.Type==TokType.FOR) return ParseFor(); if(cur.Type==TokType.IDENT){ var n=cur.Text; Next(); Expect(TokType.ASSIGN); var e=ParseExpr(); Expect(TokType.SEMI); @@ -184,6 +192,26 @@ public class StParser { return ws; } + ForStmt ParseFor(){ + Next(); // FOR + string varName = cur.Text; Expect(TokType.IDENT); + Expect(TokType.ASSIGN); + Expr start = ParseExpr(); + Expect(TokType.TO); + Expr end = ParseExpr(); + Expr step = new IntExpr(1); + if(cur.Type==TokType.BY){ + Next(); + step = ParseExpr(); + } + Expect(TokType.DO); + var fs = new ForStmt{Var=varName, Start=start, End=end, Step=step}; + while(cur.Type!=TokType.END_FOR) + fs.Body.Add(ParseStmt()); + Expect(TokType.END_FOR); Expect(TokType.SEMI); + return fs; + } + Expr ParseExpr()=>ParseCompare(); Expr ParseCompare(){ var l=ParseAddSub(); @@ -233,7 +261,7 @@ public class BytecodeEmitter { foreach(var s in p.Stmts) EmitStmt(s); - EmitByte(0xF0); + EmitByte(0xF0); // Program End } void EmitStmt(Stmt s){ @@ -264,6 +292,37 @@ public class BytecodeEmitter { PatchJump(jzpos,code.Count); break; + case ForStmt f: + // Initialisierung: var := start + EmitExpr(f.Start); + EmitByte(0x03); EmitU16((ushort)syms[f.Var].Index); + + int cmpPos = code.Count; // Position des Vergleichs + EmitExpr(new VarExpr(f.Var)); + EmitExpr(f.End); + EmitByte(0x16); // LE + EmitByte(0x20); int jzFor = code.Count; EmitU16(0); // Jump zum Ende + + // Body + foreach(var st in f.Body) EmitStmt(st); + + // Inkrement: i := i + step + EmitExpr(new VarExpr(f.Var)); + EmitExpr(f.Step); + EmitByte(0x10); // PLUS + EmitByte(0x03); EmitU16((ushort)syms[f.Var].Index); + + // Vergleich erneut, aber wir merken uns den Sprung zum Vergleich + EmitByte(0x21); EmitU16((ushort)cmpPos); + + // Patch Jump: Ende der Schleife springt hierhin + PatchJump(jzFor, code.Count); + + // Korrektur: Schleifenvariable auf Endwert, falls sie überläuft + EmitExpr(f.End); + EmitByte(0x03); EmitU16((ushort)syms[f.Var].Index); + break; + default: throw new Exception($"Unknown stmt {s.GetType().Name}"); } } diff --git a/bin/Debug/net8.0/Compiler.dll b/bin/Debug/net8.0/Compiler.dll index c063639..1561c98 100644 Binary files a/bin/Debug/net8.0/Compiler.dll and b/bin/Debug/net8.0/Compiler.dll differ diff --git a/bin/Debug/net8.0/Compiler.pdb b/bin/Debug/net8.0/Compiler.pdb index 94e808a..313a9e8 100644 Binary files a/bin/Debug/net8.0/Compiler.pdb and b/bin/Debug/net8.0/Compiler.pdb differ diff --git a/input.st b/input.st index 0ff21a2..6d064e5 100644 --- a/input.st +++ b/input.st @@ -1,10 +1,16 @@ PROGRAM Demo VAR a int16 := 0; + b int16 := 0; + i int16 := 0; END_VAR WHILE a < 5 DO a := a + 1; END_WHILE; +FOR i := 1 TO 10 DO + b := b + i; +END_FOR; + END_PROGRAM diff --git a/obj/Debug/net8.0/Compiler.AssemblyInfo.cs b/obj/Debug/net8.0/Compiler.AssemblyInfo.cs index 712a669..837a151 100644 --- a/obj/Debug/net8.0/Compiler.AssemblyInfo.cs +++ b/obj/Debug/net8.0/Compiler.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Compiler")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+384f9c719795a70259bf409ac57d221baf7a89b1")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f6aef1f0d176c5c9d337f8595797f1eb1e58a56b")] [assembly: System.Reflection.AssemblyProductAttribute("Compiler")] [assembly: System.Reflection.AssemblyTitleAttribute("Compiler")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/obj/Debug/net8.0/Compiler.AssemblyInfoInputs.cache b/obj/Debug/net8.0/Compiler.AssemblyInfoInputs.cache index 1530cbc..a361074 100644 --- a/obj/Debug/net8.0/Compiler.AssemblyInfoInputs.cache +++ b/obj/Debug/net8.0/Compiler.AssemblyInfoInputs.cache @@ -1 +1 @@ -42e892e3dd3396a02f45555f279acee4d0083d66ab01ce9b1baf7c02d466a01c +b797b871506999fe8d363a1f65cdb2c12ea0f8c34caff9806f36efedbe800822 diff --git a/obj/Debug/net8.0/Compiler.dll b/obj/Debug/net8.0/Compiler.dll index c063639..1561c98 100644 Binary files a/obj/Debug/net8.0/Compiler.dll and b/obj/Debug/net8.0/Compiler.dll differ diff --git a/obj/Debug/net8.0/Compiler.pdb b/obj/Debug/net8.0/Compiler.pdb index 94e808a..313a9e8 100644 Binary files a/obj/Debug/net8.0/Compiler.pdb and b/obj/Debug/net8.0/Compiler.pdb differ diff --git a/obj/Debug/net8.0/ref/Compiler.dll b/obj/Debug/net8.0/ref/Compiler.dll index 2ce2e2a..bd097f2 100644 Binary files a/obj/Debug/net8.0/ref/Compiler.dll and b/obj/Debug/net8.0/ref/Compiler.dll differ diff --git a/obj/Debug/net8.0/refint/Compiler.dll b/obj/Debug/net8.0/refint/Compiler.dll index 2ce2e2a..bd097f2 100644 Binary files a/obj/Debug/net8.0/refint/Compiler.dll and b/obj/Debug/net8.0/refint/Compiler.dll differ diff --git a/out.bin b/out.bin index 02dcef7..e1d75f7 100644 Binary files a/out.bin and b/out.bin differ