CompilerDesignIFLR1/CompilerDesignIflr1/LR1Closure.cs

207 lines
7.0 KiB
C#
Raw Normal View History

2024-12-20 20:20:34 +08:00
using System;
using System.Collections.Generic;
2024-12-23 01:42:58 +08:00
using System.ComponentModel;
2024-12-20 20:20:34 +08:00
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CompilerDesignIFlr1
{
internal class LR1Closure
{
2024-12-23 01:42:58 +08:00
internal static int GlobalIndex = 0;
internal int Index = 0;
internal LR1Creator LR1Creator;
internal HashSet<LR1Unit> Units { get; set; } = [];
internal Dictionary<string, int> Next { get; set; } = [];
internal LR1Closure(LR1Creator lr1Creator)
{
LR1Creator = lr1Creator;
Index = GlobalIndex++;
}
internal LR1Closure(LR1Creator lr1Creator, List<LR1Unit> units)
{
Units.UnionWith(units);
Index = GlobalIndex++;
LR1Creator = lr1Creator;
AddMissingUnits();
CalculateProspects();
}
internal void CalculateProspects()
{
//Queue<LR1Unit> queue = [];
//var startUnit = Units.Where(x=>x.Name == LR1Creator.StartSymbol).First();
//startUnit.Prospect.Add("End");
//queue.Enqueue(startUnit);
//while (queue.Count > 0)
//{
// var unit = queue.Dequeue();
// var left = unit.Name;
// var units = UnitsHaveDotBefore(left);
// var next = unit.Next();
// if (next is not null && !LR1Creator.TokenUnit.ContainsKey(next))
// foreach (var item in Units.Where(x => x.Name == next))
// queue.Enqueue(item);
// HashSet<string> prospect = units
// .Select(x => GetProspectsOf(x))
// .Aggregate(
// new HashSet<string>(),
// (set, x) =>
// {
// set.UnionWith(x);
// return set;
// }
// );
// unit.Prospect.UnionWith(prospect);
//}
bool haveChange = true;
while (haveChange)
{
haveChange = false;
foreach (var unit in Units)
{
var left = unit.Name;
var units = UnitsHaveDotBefore(left);
HashSet<string> prospect = units
.Select(x => GetProspectsOf(x))
.Aggregate(
unit.Prospect,
(set, x) =>
{
set.UnionWith(x);
return set;
}
);
if (!prospect.IsSubsetOf(unit.Prospect))
haveChange = true;
unit.Prospect.UnionWith(prospect);
}
}
}
internal List<LR1Unit> UnitsHaveDotBefore(string name)
{
List<LR1Unit> res = [];
foreach (LR1Unit unit in Units)
{
if (unit.Next() == name)
res.Add(unit);
}
return res;
}
// 对于文法 X => yz...
// 该方法返回 A => .XB 中的B 以及B可能为空时其后的元素
internal List<string> GetProspectsOf(LR1Unit unit)
{
if (unit.Name == LR1Creator.StartSymbol)
return ["End"];
//if(unit.Prospect.Count != 0)
//{
// throw new Exception("有环???");
//}
List<string> ans = unit.PointPosition + 1 == unit.Grammar.Count ? [.. unit.Prospect] : [];
for (int i = unit.PointPosition + 1; i < unit.Grammar.Count; i++)
{
var units = LR1Creator.GetUnits(unit.Grammar[i]);
ans.AddRange(LR1Creator.FirstGroup[unit.Grammar[i]]);
if (units.All(x => !x.Nullable()))
break;
else if (i == unit.Grammar.Count - 1)
ans.AddRange(unit.Prospect);
}
return ans;
}
internal void AddMissingUnits()
{
bool haveNew = true;
while (haveNew)
{
HashSet<LR1Unit> addingUnits = [];
haveNew = false;
foreach (LR1Unit unit in Units)
{
string? next = unit.Next();
if (next is null)
continue;
if (LR1Creator.GrammarUnit.TryGetValue(next, out var value))
{
var set = new HashSet<LR1Unit>(value.Select(x => x.Clone()));
if (set.IsSubsetOf(Units))
continue;
haveNew = true;
addingUnits.UnionWith(set);
}
}
Units.UnionWith(addingUnits);
}
}
internal List<LR1Closure> NextClosures()
{
List<LR1Closure> ans = [];
Dictionary<string, List<LR1Unit>> nextSteps = [];
foreach(LR1Unit unit in Units)
{
string? next = unit.Next();
if (next is null)
continue;
if (nextSteps.TryGetValue(next, out var units))
units.Add(unit);
else
nextSteps.Add(next, [unit]);
}
foreach(var (next,value) in nextSteps)
{
var closure = new LR1Closure(LR1Creator, value.Select(x => x.ToNext()).ToList());
var existClosure = LR1Creator.Closures.Values.Where(x => x.Equals(closure)).FirstOrDefault();
if(existClosure is not null)
{
LR1Closure.GlobalIndex--;
Next.Add(next,existClosure.Index);
continue;
}
ans.Add(closure);
Next.Add(next, closure.Index);
}
return ans;
}
internal List<LR1Unit> GetReduceUnits()
=> Units.Where(x => x.ReadyToReduce()).ToList();
public override bool Equals(object? obj)
{
if (obj is not LR1Closure closure || obj is null)
return false;
return closure.Units.Count == Units.Count && closure.Units.Select(x => Units.Where(y => y.Equals(x)).Any()).All(x=> x);
}
public override int GetHashCode()
{
int hash = 0;
foreach (var unit in Units.OrderBy(e => e.GetHashCode()))
{
hash ^= unit.GetHashCode();
}
return hash;
}
public override string ToString()
{
StringBuilder sb = new();
sb.Append($"闭包{Index}:\n");
foreach (var unit in Units)
{
sb.Append(unit + "\n");
}
return sb.ToString();
}
2024-12-20 20:20:34 +08:00
}
}