为了一点乐趣,我试图用C#编写一个BASIC解释器。以下是我的Tokenizer类(只有几个关键字)。我正在提出任何建议或意见......代码清晰度对我来说比效率更重要。非常感谢。
class Tokenizer
{
const string Operators = "+-/*%<>=&|";
private List<string> Keywords = new List<string>{"LET", "DIM", "PRINT", "REM"};
private List<string> tokens = new List<string>();
private List<string> tokenTypes = new List<string>();
private int tokenIndex;
// Turn command string into tokens
public void Tokenize(string cmdLine)
{
string token = "";
char lastc = ' ';
bool inString = false;
tokens.Clear();
tokenTypes.Clear();
// Step through line and split into tokens
foreach (char c in cmdLine)
{
if (c == '"') inString = !inString;
if (!inString)
{
if (IsOperator(lastc)) AddToken(ref token);
if (IsWhitespace(c)) AddToken(ref token);
if (IsOperator(c)) AddToken(ref token);
if (IsNumber(c) && !IsNumber(lastc)) AddToken(ref token);
if (!IsWhitespace(c)) token += c;
}
else
token += c;
lastc = c;
}
// Add last token
AddToken(ref token);
tokenIndex = 0;
}
public string Token()
{
return tokens[tokenIndex];
}
public string TokenType()
{
return tokenTypes[tokenIndex];
}
public void NextToken()
{
tokenIndex++;
}
public bool TokensLeft()
{
return tokenIndex < tokens.Count;
}
// Add a token to the collection
private void AddToken(ref string token)
{
if (token.Trim() != "")
{
// Determine token type
string tokenType = "Identifier";
if (IsOperator(token[0])) tokenType = "Operator";
if (IsNumber(token[0])) tokenType = "Number";
if (token[0] == '"') tokenType = "String";
if (Keywords.Contains(token.ToUpper())) tokenType = "Keyword";
tokens.Add(token);
tokenTypes.Add(tokenType);
token = "";
}
}
private bool IsWhitespace(char c)
{
return (c.ToString() != c.ToString().Trim());
}
private bool IsOperator(char c)
{
return Operators.Contains(c);
}
private bool IsNumber(char c)
{
return Char.IsNumber(c);
}
}
答案 0 :(得分:3)
你通常不想手动编写像这样的解析器代码,如果你要处理超过计算机语言的解析,学习一个好的解析器生成器工具,如Antlr是你的时间的一个很好的投资只是有趣/编码练习。话虽这么说,如果你真的想手动完成这个,你需要考虑一些事情:
这些是你会遇到的一些问题,我真的建议学习一个解析器生成器工具,它使这种事情更有趣(更不用说正确和有效)。