using System.Globalization; namespace CanonSharp.Common.LexicalAnalyzer; public class LexicalToken : IEquatable { private readonly Guid _tokenId; public RegularExpression Expression { get; } public int Priority { get; } public LexicalToken(RegularExpression expression, int priority) { _tokenId = Guid.NewGuid(); Expression = expression; Priority = priority; LiteralValue = string.Empty; } internal LexicalToken(LexicalToken definition, string literalValue) { _tokenId = definition._tokenId; Expression = definition.Expression; Priority = definition.Priority; LiteralValue = literalValue; } public string LiteralValue { get; } public bool Equals(LexicalToken? other) => other is not null && _tokenId == other._tokenId; public override bool Equals(object? obj) => obj is LexicalToken other && Equals(other); public override int GetHashCode() => _tokenId.GetHashCode(); public static bool operator ==(LexicalToken a, LexicalToken b) => a.Equals(b); public static bool operator !=(LexicalToken a, LexicalToken b) => !(a == b); /// /// 匹配所有的空白字符 /// public static readonly LexicalToken WhiteSpace = new( RegularExpression.Alternate( RegularExpression.CharSetOf(c => char.GetUnicodeCategory(c) == UnicodeCategory.SpaceSeparator), RegularExpression.CharSetOf("\u0009\u000B\u000C")), int.MinValue); /// /// 匹配所有的换行符 /// public static readonly LexicalToken LineBreaker = new( RegularExpression.Alternate( RegularExpression.CharSetOf("\u000D\u000A\u0085\u2028\u2029"), RegularExpression.String("\r\n")), int.MinValue); }