2024-03-09 23:57:43 +08:00
|
|
|
|
namespace Canon.Core.GrammarParser;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-03-10 11:22:19 +08:00
|
|
|
|
/// LR语法中的一个表达式,例如 'program_struct -> ~program_head ; program_body'
|
|
|
|
|
/// 其中'~'标识当前移进到达的位置
|
2024-03-09 23:57:43 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
public class Expression : IEquatable<Expression>
|
|
|
|
|
{
|
2024-03-10 11:22:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 表达式的左部
|
|
|
|
|
/// </summary>
|
2024-03-09 23:57:43 +08:00
|
|
|
|
public required NonTerminator Left { get; init; }
|
|
|
|
|
|
2024-03-10 11:22:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 表达式的向前看字符串
|
|
|
|
|
/// </summary>
|
2024-03-09 23:57:43 +08:00
|
|
|
|
public required Terminator LookAhead { get; init; }
|
|
|
|
|
|
2024-03-10 11:22:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 表达式的右部
|
|
|
|
|
/// </summary>
|
2024-03-09 23:57:43 +08:00
|
|
|
|
public required List<TerminatorBase> Right { get; init; }
|
|
|
|
|
|
2024-03-10 11:22:19 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 当前移进的位置
|
|
|
|
|
/// </summary>
|
2024-03-11 21:57:47 +08:00
|
|
|
|
public required int Pos { get; init; }
|
2024-03-09 23:57:43 +08:00
|
|
|
|
|
|
|
|
|
public bool Equals(Expression? other)
|
|
|
|
|
{
|
|
|
|
|
if (other is null)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Right.Count != other.Right.Count)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Right.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (Right[i].IsTerminated != other.Right[i].IsTerminated)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Right[i].Equals(other.Right[i]))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Left == other.Left
|
2024-03-11 21:57:47 +08:00
|
|
|
|
&& LookAhead == other.LookAhead
|
|
|
|
|
&& Pos == other.Pos;
|
2024-03-09 23:57:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool Equals(object? obj)
|
|
|
|
|
{
|
|
|
|
|
if (obj is not Expression other)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Equals(other);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
|
{
|
|
|
|
|
int hash = Left.GetHashCode();
|
|
|
|
|
hash ^= LookAhead.GetHashCode();
|
2024-03-11 21:57:47 +08:00
|
|
|
|
hash ^= Pos.GetHashCode();
|
2024-03-09 23:57:43 +08:00
|
|
|
|
|
|
|
|
|
foreach (TerminatorBase terminator in Right)
|
|
|
|
|
{
|
|
|
|
|
hash ^= terminator.GetHashCode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 19:33:02 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
string result = $"{Left} -> ";
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Right.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i == Pos)
|
|
|
|
|
{
|
|
|
|
|
result += '~';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result += ' ';
|
|
|
|
|
result += Right[i].ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 21:57:47 +08:00
|
|
|
|
if (Pos == Right.Count)
|
|
|
|
|
{
|
|
|
|
|
result += '~';
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-11 19:33:02 +08:00
|
|
|
|
result += $", {LookAhead}";
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-09 23:57:43 +08:00
|
|
|
|
public static bool operator ==(Expression a, Expression b)
|
|
|
|
|
{
|
|
|
|
|
return a.Equals(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool operator !=(Expression a, Expression b)
|
|
|
|
|
{
|
|
|
|
|
return !a.Equals(b);
|
|
|
|
|
}
|
|
|
|
|
}
|