FOR
This commit is contained in:
61
Program.cs
61
Program.cs
@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// === ENTRY POINT ===
|
||||||
class Program {
|
class Program {
|
||||||
static int Main(string[] args) {
|
static int Main(string[] args) {
|
||||||
if (args.Length < 2) {
|
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 AssignStmt:Stmt{ public string Target; public Expr Expr; }
|
||||||
public class IfStmt:Stmt{ public Expr Cond; public List<Stmt> ThenStmts=new(); public List<Stmt> ElseStmts=new(); }
|
public class IfStmt:Stmt{ public Expr Cond; public List<Stmt> ThenStmts=new(); public List<Stmt> ElseStmts=new(); }
|
||||||
public class WhileStmt:Stmt{ public Expr Cond; public List<Stmt> Body=new(); }
|
public class WhileStmt:Stmt{ public Expr Cond; public List<Stmt> Body=new(); }
|
||||||
|
public class ForStmt:Stmt{ public string Var; public Expr Start, End, Step = new IntExpr(1); public List<Stmt> Body=new(); }
|
||||||
|
|
||||||
public abstract class Expr:StNode{}
|
public abstract class Expr:StNode{}
|
||||||
public class IntExpr:Expr{ public int Value; public IntExpr(int v){Value=v;} }
|
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,
|
LT, GT, LE, GE, EQ, NEQ,
|
||||||
IF, THEN, ELSE, END_IF,
|
IF, THEN, ELSE, END_IF,
|
||||||
WHILE, DO, END_WHILE,
|
WHILE, DO, END_WHILE,
|
||||||
|
FOR, TO, BY, END_FOR,
|
||||||
PROGRAM, VAR, END_VAR, END_PROGRAM,
|
PROGRAM, VAR, END_VAR, END_PROGRAM,
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@ -75,6 +78,10 @@ public class StLexer {
|
|||||||
"WHILE"=>new Token(TokType.WHILE,s),
|
"WHILE"=>new Token(TokType.WHILE,s),
|
||||||
"DO"=>new Token(TokType.DO,s),
|
"DO"=>new Token(TokType.DO,s),
|
||||||
"END_WHILE"=>new Token(TokType.END_WHILE,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)
|
_=>new Token(TokType.IDENT,s)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -151,6 +158,7 @@ public class StParser {
|
|||||||
Stmt ParseStmt(){
|
Stmt ParseStmt(){
|
||||||
if(cur.Type==TokType.IF) return ParseIf();
|
if(cur.Type==TokType.IF) return ParseIf();
|
||||||
if(cur.Type==TokType.WHILE) return ParseWhile();
|
if(cur.Type==TokType.WHILE) return ParseWhile();
|
||||||
|
if(cur.Type==TokType.FOR) return ParseFor();
|
||||||
if(cur.Type==TokType.IDENT){
|
if(cur.Type==TokType.IDENT){
|
||||||
var n=cur.Text; Next(); Expect(TokType.ASSIGN);
|
var n=cur.Text; Next(); Expect(TokType.ASSIGN);
|
||||||
var e=ParseExpr(); Expect(TokType.SEMI);
|
var e=ParseExpr(); Expect(TokType.SEMI);
|
||||||
@ -184,6 +192,26 @@ public class StParser {
|
|||||||
return ws;
|
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 ParseExpr()=>ParseCompare();
|
||||||
Expr ParseCompare(){
|
Expr ParseCompare(){
|
||||||
var l=ParseAddSub();
|
var l=ParseAddSub();
|
||||||
@ -233,7 +261,7 @@ public class BytecodeEmitter {
|
|||||||
foreach(var s in p.Stmts)
|
foreach(var s in p.Stmts)
|
||||||
EmitStmt(s);
|
EmitStmt(s);
|
||||||
|
|
||||||
EmitByte(0xF0);
|
EmitByte(0xF0); // Program End
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitStmt(Stmt s){
|
void EmitStmt(Stmt s){
|
||||||
@ -264,6 +292,37 @@ public class BytecodeEmitter {
|
|||||||
PatchJump(jzpos,code.Count);
|
PatchJump(jzpos,code.Count);
|
||||||
break;
|
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}");
|
default: throw new Exception($"Unknown stmt {s.GetType().Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
6
input.st
6
input.st
@ -1,10 +1,16 @@
|
|||||||
PROGRAM Demo
|
PROGRAM Demo
|
||||||
VAR
|
VAR
|
||||||
a int16 := 0;
|
a int16 := 0;
|
||||||
|
b int16 := 0;
|
||||||
|
i int16 := 0;
|
||||||
END_VAR
|
END_VAR
|
||||||
|
|
||||||
WHILE a < 5 DO
|
WHILE a < 5 DO
|
||||||
a := a + 1;
|
a := a + 1;
|
||||||
END_WHILE;
|
END_WHILE;
|
||||||
|
|
||||||
|
FOR i := 1 TO 10 DO
|
||||||
|
b := b + i;
|
||||||
|
END_FOR;
|
||||||
|
|
||||||
END_PROGRAM
|
END_PROGRAM
|
||||||
|
|||||||
@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Compiler")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Compiler")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[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.AssemblyProductAttribute("Compiler")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Compiler")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Compiler")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
42e892e3dd3396a02f45555f279acee4d0083d66ab01ce9b1baf7c02d466a01c
|
b797b871506999fe8d363a1f65cdb2c12ea0f8c34caff9806f36efedbe800822
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user