180 lines
5.1 KiB
C#
180 lines
5.1 KiB
C#
using System.Diagnostics.SymbolStore;
|
|
using System.Text;
|
|
|
|
namespace CompilerDesignIFlr1
|
|
{
|
|
internal class LR1Unit
|
|
{
|
|
internal LR1Unit() { }
|
|
|
|
internal static string LanguageMode = "English";
|
|
internal static Dictionary<string, string> EnglishToChinese = [];
|
|
internal static void Init(string filePath)
|
|
{
|
|
string fileContent = File.ReadAllText(filePath);
|
|
EnglishToChinese = fileContent
|
|
.Split('#')
|
|
.Select(x => x.Split(':').Select(x => x.Trim()).ToList()).Where(x=>x.Count == 2).ToList().ToDictionary(x => x[0], x => x[1]);
|
|
}
|
|
|
|
internal LR1Unit(string name, string grammar)
|
|
{
|
|
Type = "Token";
|
|
Name = name;
|
|
Grammar = [grammar];
|
|
}
|
|
|
|
internal LR1Unit(string name, string value, string grammar)
|
|
{
|
|
Type = "Token";
|
|
Name = name;
|
|
Grammar = [grammar];
|
|
Value = value;
|
|
}
|
|
|
|
internal LR1Unit(string name, List<string> grammar)
|
|
{
|
|
Type = "Grammar";
|
|
Name = name;
|
|
Grammar = grammar;
|
|
}
|
|
|
|
internal LR1Unit(
|
|
int id,
|
|
string type,
|
|
string name,
|
|
HashSet<string> prospect,
|
|
int pointPosition,
|
|
List<string> grammar
|
|
)
|
|
{
|
|
Id = id;
|
|
Type = type;
|
|
Name = name;
|
|
Prospect = prospect;
|
|
PointPosition = pointPosition;
|
|
Grammar = grammar;
|
|
}
|
|
|
|
public LR1Unit(
|
|
int id,
|
|
string type,
|
|
string name,
|
|
int quadrupleIndex,
|
|
string value,
|
|
HashSet<string> prospect,
|
|
int pointPosition,
|
|
List<string> grammar
|
|
)
|
|
{
|
|
Id = id;
|
|
Type = type;
|
|
Name = name;
|
|
QuadrupleIndex = quadrupleIndex;
|
|
Value = value;
|
|
Prospect = prospect;
|
|
PointPosition = pointPosition;
|
|
Grammar = grammar;
|
|
}
|
|
|
|
internal LR1Unit Clone() =>
|
|
new LR1Unit(
|
|
Id,
|
|
Type,
|
|
Name,
|
|
0,
|
|
Value,
|
|
new HashSet<string>(Prospect),
|
|
PointPosition,
|
|
[.. Grammar]
|
|
);
|
|
|
|
internal int Id { get; set; } = -1;
|
|
internal string Type { get; set; } = "";
|
|
internal string Name { get; set; } = "";
|
|
internal int QuadrupleIndex { get; set; } = 0;
|
|
internal string Value { get; set; } = "";
|
|
internal HashSet<string> Prospect { get; set; } = [];
|
|
internal int PointPosition { get; set; } = 0;
|
|
internal List<string> Grammar { get; set; } = [];
|
|
|
|
internal string? Next() => PointPosition >= Grammar.Count ? null : Grammar[PointPosition];
|
|
|
|
internal bool ReadyToReduce() => PointPosition >= Grammar.Count;
|
|
|
|
internal bool CanReduce(List<LR1Unit> stack)
|
|
{
|
|
for (int i = 1; i <= Grammar.Count; i++)
|
|
{
|
|
if (stack[^i].Name != Grammar[^i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
string GetName(string s)
|
|
{
|
|
return LanguageMode switch
|
|
{
|
|
"Chinese" => EnglishToChinese.TryGetValue(s, out var result) ? result : s,
|
|
"English" => s,
|
|
_ => throw new Exception("Language mode is not supported.")
|
|
};
|
|
}
|
|
StringBuilder sb = new();
|
|
sb.Append($"{Id, 2} ");
|
|
sb.Append(GetName(Name)).Append(" ::= ");
|
|
for (int i = 0; i < Grammar.Count; i++)
|
|
{
|
|
if (PointPosition == i)
|
|
sb.Append(". ");
|
|
sb.Append(GetName(Grammar[i]) + " ");
|
|
}
|
|
if (PointPosition == Grammar.Count)
|
|
sb.Append('.');
|
|
foreach (var item in Prospect)
|
|
{
|
|
sb.Append(", " + GetName(item));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
if (obj is not LR1Unit other)
|
|
return false;
|
|
|
|
return Type == other.Type
|
|
&& Name == other.Name
|
|
&& Id == other.Id
|
|
&& PointPosition == other.PointPosition
|
|
&& Grammar.SequenceEqual(other.Grammar)
|
|
&& Prospect.SetEquals(other.Prospect);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
HashCode hash = new HashCode();
|
|
hash.Add(Type);
|
|
hash.Add(Name);
|
|
hash.Add(PointPosition);
|
|
foreach (var item in Grammar)
|
|
hash.Add(item);
|
|
foreach (var item in Prospect)
|
|
hash.Add(item);
|
|
return hash.ToHashCode();
|
|
}
|
|
|
|
internal bool Nullable() => Grammar.Count == 0;
|
|
|
|
internal LR1Unit ToNext()
|
|
{
|
|
var unit = Clone();
|
|
unit.PointPosition++;
|
|
return unit;
|
|
}
|
|
}
|
|
}
|