using System.Globalization; using System.Text; namespace langtest { public enum LexTokenType { PLUS=0, MINUS=1, MULTIPLY=2, DIVIDE=3, MOD=4, LPAREN=5, RPAREN=6, IDENTIFER=7, NUMBER=8, EQUALS=9, COMMA=10, ERROR=11, SEMI=12, LBRACE=13, RBRACE=14, STRING=15, } public class LexToken { public LexToken() { } public LexToken(string text) { Text = text; Type=char.IsLetter(text.FirstOrDefault()) ? LexTokenType.IDENTIFER : (char.IsNumber(text.FirstOrDefault()) ? LexTokenType.NUMBER : LexTokenType.ERROR); } public LexTokenType Type {get;set;} public string Text {get;set;}=""; } public static class Lexer { public static string? Prompt(string t) { Console.Write(t); return Console.ReadLine(); } public static IEnumerable EnumerateTokens(string text) { int filePos=0; Func<(char chr,bool esc)> read_char = ()=>{ int txt=text[filePos++]; if(txt == '\\') { //we are to escape txt = text[filePos++]; if(txt == 'x') { char[] chars=new char[4]; for(int i = 0 ;i<4;i++) { txt = text[filePos++]; chars[i] = (char)txt; } return ((char)Int16.Parse(new string(chars), NumberStyles.AllowHexSpecifier),true); }else{ if(txt == 'n') { return ('\n',true); } if(txt == 'r') { return ('\r',true); } if(txt == 't') { return ('\t',true); } return ((char)txt,true); } } else{ return ((char)txt,false); } }; Func read_string = ()=>{ StringBuilder b=new StringBuilder(); while(true) { (char chr,bool esc) txt=read_char(); if(txt.chr == '\"' && !txt.esc) { break; } b.Append(txt.chr); } return b.ToString(); }; StringBuilder b=new StringBuilder(); while(filePos < text.Length) { char c=text[filePos++]; if(c == '\"') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } string str = read_string(); yield return new LexToken(){Text = str,Type = LexTokenType.STRING}; } else if(c == '\'') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } char str = read_char().chr; filePos++; yield return new LexToken(){Text = ((int)str).ToString(),Type = LexTokenType.NUMBER}; }else if(c == '+') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="+",Type = LexTokenType.PLUS}; }else if(c == '-') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="-",Type = LexTokenType.MINUS}; }else if(c == '*') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="*",Type = LexTokenType.MULTIPLY}; }else if(c == '/') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="/",Type = LexTokenType.DIVIDE}; }else if(c == '%') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="%",Type = LexTokenType.MOD}; }else if(c == '{') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="{",Type = LexTokenType.LBRACE}; }else if(c == '}') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="}",Type = LexTokenType.RBRACE}; } else if(c == '(') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="(",Type = LexTokenType.LPAREN}; }else if(c == ')') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text=")",Type = LexTokenType.RPAREN}; }else if(c == '=') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text="=",Type = LexTokenType.EQUALS}; } else if(c == ',') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text=",",Type = LexTokenType.COMMA}; } else if(c == ';') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } yield return new LexToken(){Text=";",Type = LexTokenType.SEMI}; } else if(c == '\n' || c == ' ' || c == '\t') { if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } }else{ b.Append(c); } } if(b.Length > 0) { yield return new LexToken(b.ToString()); b.Clear(); } } } }