using System; using System.Collections.Generic; namespace Amogulator.Suslang; public enum TokenType { Eof, Invalid, Id, Int, Hex, Decimal, String, True, False, LParen, RParen, Plus, Minus, Asterisk, Slash, Percent, } public struct Position { public int index; public int line, col; } public struct Token { public TokenType type; public Position position; public int length; } public class Lexer { private int i = 0; private string text; private int line = 1; private int col = 1; public Lexer(string text) { this.text = text; } public Token next() { if (done()) { return token(TokenType.Eof, position()); } else if ("123456789".Contains(current())) { return intToken(); } else if ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".Contains(current())) { return idToken(); } else { return staticToken(); } } private Token intToken() { var start = position(); var value = ""; value += current(); step(); while (!done() && "1234567890".Contains(current())) { value += current(); step(); } return token(TokenType.Int, start); } private Token idToken() { var start = position(); var value = ""; value += current(); step(); while (!done() && "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".Contains(current())) { value += current(); step(); } return token(TokenType.Id, start); } private Token staticToken() { var start = position(); switch (current()) { case '(': step(); return token(TokenType.LParen, start); case ')': step(); return token(TokenType.RParen, start); case '+': step(); return token(TokenType.Plus, start); case '-': step(); return token(TokenType.Minus, start); case '*': step(); return token(TokenType.Asterisk, start); case '/': step(); return token(TokenType.Slash, start); case '%': step(); return token(TokenType.Percent, start); default: step(); return token(TokenType.Invalid, start); } } private Token token(TokenType type, Position start) => new Token() { type = type, position = start, length = this.i - start.index, }; private Position position() => new Position() { index = this.i, line = this.line, col = this.col, }; private char current() => this.text[this.i]; private bool done() => this.i >= this.text.Length; private void step() { this.i += 1; } } public interface Expr { } public class Parser { public Expr parseExpr() { throw new NotImplementedException(); } } public interface Operation { } public class Compiler { public List compileExpr(Expr expr) { throw new NotImplementedException(); } } public interface Value { } public class VM { public Value evaluate(List program) { throw new NotImplementedException(); } }