@@ -4,60 +4,57 @@ namespace Canon.Core.LexicalParser;
|
||||
|
||||
public static class LexemeFactory
|
||||
{
|
||||
|
||||
public static SemanticToken MakeToken(SemanticTokenType tokenType,string literal,uint _line,uint _chPos)
|
||||
public static SemanticToken MakeToken(SemanticTokenType tokenType,string literal,uint line,uint chPos)
|
||||
{
|
||||
SemanticToken? token;
|
||||
switch (tokenType)
|
||||
{
|
||||
case SemanticTokenType.Character:
|
||||
CharacterSemanticToken characterSemanticToken = new CharacterSemanticToken()
|
||||
CharacterSemanticToken characterSemanticToken = new()
|
||||
{
|
||||
LinePos = _line, CharacterPos = _chPos, LiteralValue = literal,
|
||||
LinePos = line, CharacterPos = chPos, LiteralValue = literal,
|
||||
};
|
||||
token = characterSemanticToken;
|
||||
break;
|
||||
case SemanticTokenType.Identifier:
|
||||
IdentifierSemanticToken identifierSemanticToken = new IdentifierSemanticToken()
|
||||
IdentifierSemanticToken identifierSemanticToken = new()
|
||||
{
|
||||
LinePos = _line, CharacterPos = _chPos, LiteralValue = literal,
|
||||
LinePos = line, CharacterPos = chPos, LiteralValue = literal,
|
||||
};
|
||||
token = identifierSemanticToken;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(tokenType), tokenType, null);
|
||||
throw new InvalidOperationException("Can only create Character or Identifier SemanticToken.");
|
||||
}
|
||||
|
||||
return token;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static KeywordSemanticToken MakeToken(KeywordType keywordType,string literal,uint _line,uint _chPos)
|
||||
public static KeywordSemanticToken MakeToken(KeywordType keywordType,string literal,uint line,uint chPos)
|
||||
{
|
||||
KeywordSemanticToken keywordSemanticToken = new KeywordSemanticToken
|
||||
KeywordSemanticToken keywordSemanticToken = new()
|
||||
{
|
||||
LinePos = _line,
|
||||
CharacterPos = _chPos,
|
||||
LinePos = line,
|
||||
CharacterPos = chPos,
|
||||
LiteralValue = literal,
|
||||
KeywordType = keywordType
|
||||
};
|
||||
return keywordSemanticToken;
|
||||
}
|
||||
|
||||
public static DelimiterSemanticToken MakeToken(DelimiterType delimiterType,string literal,uint _line,uint _chPos)
|
||||
public static DelimiterSemanticToken MakeToken(DelimiterType delimiterType,string literal,uint line,uint chPos)
|
||||
{
|
||||
DelimiterSemanticToken delimiterSemanticToken = new DelimiterSemanticToken()
|
||||
DelimiterSemanticToken delimiterSemanticToken = new()
|
||||
{
|
||||
LinePos = _line,
|
||||
CharacterPos = _chPos,
|
||||
LinePos = line,
|
||||
CharacterPos = chPos,
|
||||
LiteralValue = literal,
|
||||
DelimiterType = delimiterType
|
||||
};
|
||||
return delimiterSemanticToken;
|
||||
}
|
||||
|
||||
public static NumberSemanticToken MakeToken(NumberType numberType,string literal,uint _line,uint _chPos)
|
||||
public static NumberSemanticToken MakeToken(NumberType numberType,string literal,uint line,uint chPos)
|
||||
{
|
||||
string temp = literal;
|
||||
string result;
|
||||
@@ -70,10 +67,10 @@ public static class LexemeFactory
|
||||
result = temp;
|
||||
}
|
||||
|
||||
NumberSemanticToken numberSemanticToken = new NumberSemanticToken()
|
||||
NumberSemanticToken numberSemanticToken = new()
|
||||
{
|
||||
LinePos = _line,
|
||||
CharacterPos = _chPos,
|
||||
LinePos = line,
|
||||
CharacterPos = chPos,
|
||||
LiteralValue = result,
|
||||
NumberType = numberType
|
||||
};
|
||||
@@ -81,12 +78,12 @@ public static class LexemeFactory
|
||||
|
||||
}
|
||||
|
||||
public static OperatorSemanticToken MakeToken(OperatorType operatorType,string literal,uint _line,uint _chPos)
|
||||
public static OperatorSemanticToken MakeToken(OperatorType operatorType,string literal,uint line,uint chPos)
|
||||
{
|
||||
OperatorSemanticToken operatorSemanticToken = new OperatorSemanticToken()
|
||||
OperatorSemanticToken operatorSemanticToken = new()
|
||||
{
|
||||
LinePos = _line,
|
||||
CharacterPos = _chPos,
|
||||
LinePos = line,
|
||||
CharacterPos = chPos,
|
||||
LiteralValue = literal,
|
||||
OperatorType = operatorType
|
||||
};
|
||||
|
@@ -22,21 +22,10 @@ public class Lexer : ILexer
|
||||
private uint _line = 1;
|
||||
private uint _chPos;
|
||||
|
||||
// Token统计信息
|
||||
private readonly Dictionary<SemanticTokenType, int> _tokenCount = new()
|
||||
{
|
||||
{ SemanticTokenType.Keyword, 0 },
|
||||
{ SemanticTokenType.Number, 0 },
|
||||
{ SemanticTokenType.Operator, 0 },
|
||||
{ SemanticTokenType.Delimiter, 0 },
|
||||
{ SemanticTokenType.Identifier, 0 },
|
||||
{ SemanticTokenType.Character, 0 },
|
||||
{ SemanticTokenType.End, 0 }
|
||||
};
|
||||
|
||||
public IEnumerable<SemanticToken> Tokenize(ISourceReader reader)
|
||||
{
|
||||
_reader = reader;
|
||||
_state = StateType.Start;
|
||||
|
||||
while (_state != StateType.Done)
|
||||
{
|
||||
@@ -526,7 +515,11 @@ public class Lexer : ILexer
|
||||
break;
|
||||
}
|
||||
|
||||
AddToTokens(_semanticToken);
|
||||
if (_semanticToken is null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
_tokens.Add(_semanticToken);
|
||||
_state = StateType.Start;
|
||||
}
|
||||
|
||||
@@ -614,9 +607,6 @@ public class Lexer : ILexer
|
||||
private void AddToTokens(SemanticToken semanticToken)
|
||||
{
|
||||
_tokens.Add(semanticToken);
|
||||
_tokenCount[semanticToken.TokenType]++;
|
||||
Console.WriteLine($"<{semanticToken.TokenType}>");
|
||||
Console.WriteLine(semanticToken.LiteralValue);
|
||||
}
|
||||
|
||||
private void Cat()
|
||||
|
@@ -54,12 +54,13 @@ public abstract class SemanticToken : IEquatable<SemanticToken>
|
||||
/// </summary>
|
||||
public static EndSemanticToken End => new()
|
||||
{
|
||||
LinePos = 0, CharacterPos = 0, LiteralValue = string.Empty
|
||||
LinePos = uint.MaxValue, CharacterPos = uint.MaxValue, LiteralValue = string.Empty
|
||||
};
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"LinePos: {LinePos}, CharacterPos: {CharacterPos}, LiteralValue: {LiteralValue}, TokenType: {TokenType}";
|
||||
return
|
||||
$"LinePos: {LinePos}, CharacterPos: {CharacterPos}, LiteralValue: {LiteralValue}, TokenType: {TokenType}";
|
||||
}
|
||||
|
||||
public bool Equals(SemanticToken? other)
|
||||
@@ -93,13 +94,6 @@ public abstract class SemanticToken : IEquatable<SemanticToken>
|
||||
public class CharacterSemanticToken : SemanticToken
|
||||
{
|
||||
public override SemanticTokenType TokenType => SemanticTokenType.Character;
|
||||
|
||||
public static bool TryParse(uint linePos, uint characterPos, LinkedListNode<char> now,
|
||||
out CharacterSemanticToken? token)
|
||||
{
|
||||
token = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -146,7 +140,7 @@ public class DelimiterSemanticToken : SemanticToken
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode() ^ this.DelimiterType.GetHashCode();
|
||||
return base.GetHashCode() ^ DelimiterType.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,33 +153,34 @@ public class KeywordSemanticToken : SemanticToken
|
||||
|
||||
public required KeywordType KeywordType { get; init; }
|
||||
|
||||
public static readonly Dictionary<string, KeywordType> KeywordTypes = new Dictionary<string, KeywordType>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "program", KeywordType.Program },
|
||||
{ "const", KeywordType.Const },
|
||||
{ "var", KeywordType.Var },
|
||||
{ "procedure", KeywordType.Procedure },
|
||||
{ "function", KeywordType.Function },
|
||||
{ "begin", KeywordType.Begin },
|
||||
{ "end", KeywordType.End },
|
||||
{ "array", KeywordType.Array },
|
||||
{ "of", KeywordType.Of },
|
||||
{ "if", KeywordType.If },
|
||||
{ "then", KeywordType.Then },
|
||||
{ "else", KeywordType.Else },
|
||||
{ "for", KeywordType.For },
|
||||
{ "to", KeywordType.To },
|
||||
{ "do", KeywordType.Do },
|
||||
{ "integer", KeywordType.Integer },
|
||||
{ "real", KeywordType.Real },
|
||||
{ "boolean", KeywordType.Boolean },
|
||||
{ "character", KeywordType.Character },
|
||||
{ "div", KeywordType.Divide }, // 注意: Pascal 使用 'div' 而不是 '/'
|
||||
{ "not", KeywordType.Not },
|
||||
{ "mod", KeywordType.Mod },
|
||||
{ "and", KeywordType.And },
|
||||
{ "or", KeywordType.Or }
|
||||
};
|
||||
public static readonly Dictionary<string, KeywordType> KeywordTypes =
|
||||
new Dictionary<string, KeywordType>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "program", KeywordType.Program },
|
||||
{ "const", KeywordType.Const },
|
||||
{ "var", KeywordType.Var },
|
||||
{ "procedure", KeywordType.Procedure },
|
||||
{ "function", KeywordType.Function },
|
||||
{ "begin", KeywordType.Begin },
|
||||
{ "end", KeywordType.End },
|
||||
{ "array", KeywordType.Array },
|
||||
{ "of", KeywordType.Of },
|
||||
{ "if", KeywordType.If },
|
||||
{ "then", KeywordType.Then },
|
||||
{ "else", KeywordType.Else },
|
||||
{ "for", KeywordType.For },
|
||||
{ "to", KeywordType.To },
|
||||
{ "do", KeywordType.Do },
|
||||
{ "integer", KeywordType.Integer },
|
||||
{ "real", KeywordType.Real },
|
||||
{ "boolean", KeywordType.Boolean },
|
||||
{ "character", KeywordType.Character },
|
||||
{ "div", KeywordType.Divide }, // 注意: Pascal 使用 'div' 而不是 '/'
|
||||
{ "not", KeywordType.Not },
|
||||
{ "mod", KeywordType.Mod },
|
||||
{ "and", KeywordType.And },
|
||||
{ "or", KeywordType.Or }
|
||||
};
|
||||
|
||||
public static KeywordType GetKeywordTypeByKeyword(string keyword)
|
||||
{
|
||||
@@ -199,56 +194,6 @@ public class KeywordSemanticToken : SemanticToken
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryParse(uint linePos, uint characterPos, LinkedListNode<char> now,
|
||||
out KeywordSemanticToken? token)
|
||||
{
|
||||
string buffer = new([now.Value]);
|
||||
|
||||
if (now.Next is null)
|
||||
{
|
||||
// 没有比两个字符更短的关键字
|
||||
token = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
now = now.Next;
|
||||
buffer += now.Value;
|
||||
|
||||
switch (buffer)
|
||||
{
|
||||
case "do":
|
||||
token = new KeywordSemanticToken
|
||||
{
|
||||
LinePos = linePos,
|
||||
CharacterPos = characterPos,
|
||||
LiteralValue = "do",
|
||||
KeywordType = KeywordType.Do
|
||||
};
|
||||
return true;
|
||||
case "Of":
|
||||
token = new KeywordSemanticToken
|
||||
{
|
||||
LinePos = linePos,
|
||||
CharacterPos = characterPos,
|
||||
LiteralValue = "of",
|
||||
KeywordType = KeywordType.Of
|
||||
};
|
||||
return true;
|
||||
case "If":
|
||||
token = new KeywordSemanticToken
|
||||
{
|
||||
LinePos = linePos,
|
||||
CharacterPos = characterPos,
|
||||
LiteralValue = "if",
|
||||
KeywordType = KeywordType.If
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
token = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode() ^ this.KeywordType.GetHashCode();
|
||||
@@ -291,16 +236,9 @@ public class OperatorSemanticToken : SemanticToken
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryParse(uint linePos, uint characterPos, LinkedListNode<char> now,
|
||||
out OperatorSemanticToken? token)
|
||||
{
|
||||
token = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode() ^ this.OperatorType.GetHashCode();
|
||||
return base.GetHashCode() ^ OperatorType.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +253,7 @@ public class NumberSemanticToken : SemanticToken
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode() ^ this.NumberType.GetHashCode();
|
||||
return base.GetHashCode() ^ NumberType.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,17 +264,13 @@ public class IdentifierSemanticToken : SemanticToken
|
||||
{
|
||||
public override SemanticTokenType TokenType => SemanticTokenType.Identifier;
|
||||
|
||||
public static bool TryParse(uint linePos, uint characterPos, LinkedListNode<char> now,
|
||||
out IdentifierSemanticToken? token)
|
||||
{
|
||||
token = null;
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 标识符名称
|
||||
/// </summary>
|
||||
public string IdentifierName => LiteralValue.ToLower();
|
||||
}
|
||||
|
||||
public class EndSemanticToken : SemanticToken
|
||||
{
|
||||
public override SemanticTokenType TokenType => SemanticTokenType.End;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user