boxscript-interperter/Lexer.cs

267 lines
8.2 KiB
C#

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<LexToken> 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<string> 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();
}
}
}
}