term { ("+" | "-") term } ; term = factor { ("*" | "/") factor } ; factor = num | "(" expression ")" ; num = 今回は省略; class Ast // 次のページ以降スペースの都合上 class ではなく record を使うが意味は同じ。 { public IToken Expression { get; } public Ast(IToken expression) { Expression = expression; } } class Parser { public Ast Parse() => new Ast(ParseExpression()); } 12
; record Mul(IToken Left, IToken Right) : IToken, IBinaryOp; record Div(IToken Left, IToken Right) : IToken, IBinaryOp; class Parser { public IToken ParseTerm() { IToken left = ParseFactor(); while (PeekNextChar() is "*" or "/") { char op = ReadNextChar(); IToken right = ParseFactor(); left = (op == "*") ? new Mul(left, right) : new Div(left, right); } return left; } } 14
insts.Add(new RetInst()); } static void Traversal(IToken token, List<IInst> insts) { if (token is Num num) { insts.Add(new PushInst(num.Value)); } else if (token is IBinaryOp binOp) { Traversal(binOp.Left, insts); Traversal(binOp.Right, insts); insts.Add(binOp switch { Add => new AddInst(), Sub => new SubInst(), Mul => new MulInst(), Div => new DivInst(), _ => throw new Exception(), }); } } 24
int sp = 0; // stack pointer int pc = 0; // program counter while (true) { switch (program[pc++]) { case 0x00: // push stack[sp++] = BitConverter.ToSingle(program.AsSpan(pc, 4)); pc += 4; break; case 0x01: // add float right = stack[--sp]; float left = stack[--sp]; stack[sp++] = left + right; break; // ... 他の命令は省略 ... case 0x05: // ret return stack[--sp]; } } } 27