FOR
This commit is contained in:
61
Program.cs
61
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<Stmt> ThenStmts=new(); public List<Stmt> ElseStmts=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 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}");
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
6
input.st
6
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
|
||||
|
||||
@ -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")]
|
||||
|
||||
@ -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