using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using miew.Debugging;
using miew.Enumerable;
using miew.Tokenization;
using miew.String;
using miew.String.Builder;
using miew.Concurrency;
namespace agree
{
public abstract partial class PassiveEdge : ArrayTfs, IParseObj
{
#if DEBUG
public partial class Derived : PassiveEdge
{
public void DumpDerivations(TextWriter tw = null)
{
tw = tw ?? Console.Out;
System.Text.StringBuilder sb = null;
if (_packed_edges == null)
return;
sb = new System.Text.StringBuilder();
sb.AppendFormatLine("================== {0} ================", this.ToString());
sb.AppendFormatLine("daughters:");
IDerivation[][] rgrg = new IDerivation[rgo.Count][];
for (int j = 0; j < rgo.Count; j++)
{
rgrg[j] = rgo[j].Derivations.ToArray();
sb.AppendFormatLine(" #{0} derivations: {1}", j, rgrg[j].Length);
for (int k = 0; k < rgrg[j].Length; k++)
{
sb.AppendFormatLine(" {0}", rgrg[j][k].ToString());
}
}
sb.AppendLine();
sb.AppendFormatLine("packed: {0} edges", _packed_edges.Count);
int i = 0;
foreach (Derived dpe in _packed_edges)
{
sb.AppendFormatLine(" packed edge #{0} {1} derivations: {2}", i++, dpe.ToString(), dpe.Derivations.Count);
foreach (IDerivation dv in dpe.Derivations)
{
sb.AppendFormatLine(" === dv #{0} {1} ===", i++, dv.Source.ToString());
//sb.AppendFormatLine("{0}", dv.TreeDisplay().ToString());
if (dv is ParseTree)
sb.AppendLine(((ParseTree)dv).Select(d => d.ToString()).StringJoin(Environment.NewLine).Indent(8));
else
sb.AppendLine(" " + ((LexicalAnalysis.AnalysisStack)dv).ToString());
sb.AppendLine();
//sb.AppendFormatLine(" {0}", dpe.rgo[j].ToString());
//for (int j = 0; j < rgo.Count; j++)
//{
// sb.AppendFormatLine(" {0}", dpe.rgo[j].ToString());
//}
}
}
sb.AppendLine();
sb.AppendFormatLine("cross-product: {0}", _parse_trees.Length);
i = 0;
foreach (var dv in _parse_trees)
{
sb.AppendFormatLine(" === dv #{0} {1} ===", i++, dv.Source.ToString());
//sb.AppendFormatLine("{0}", dv.TreeDisplay().ToString());
if (dv is ParseTree)
sb.AppendLine(((ParseTree)dv).Select(d => d.ToString()).StringJoin(Environment.NewLine).Indent(8));
else
sb.AppendLine(" " + ((LexicalAnalysis.AnalysisStack)dv).ToString());
sb.AppendLine();
}
sb.AppendLine();
tw.WriteLine(sb.ToString());
}
};
[DebuggerDisplay("{ToString(),nq}")]
public partial class ParseTree : IDerivation, IList<IDerivation>
{
static int next_id = 0;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public readonly int id;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ParseTree[] _TREE
{
get
{
ParseTree[] rg = new ParseTree[daughters.Length];
for (int i = 0; i < daughters.Length; i++)
rg[i] = daughters[i] as ParseTree ??
new LexEntryPlaceholder(ctrl, (LexicalAnalysis.AnalysisStack)daughters[i]);
return rg;
}
}
[DebuggerDisplay("{ToString(),nq}")]
public class LexEntryPlaceholder : ParseTree
{
LexicalAnalysis.AnalysisStack stk;
public LexEntryPlaceholder(ParseControl ctrl, LexicalAnalysis.AnalysisStack stk)
: base(ctrl, stk, null)
{
this.stk = stk;
}
public override string ToString()
{
return stk.ToString();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public override string ToString()
{
int p = 0;
String pp = "";
if (mother is PassiveEdge)
{
PassiveEdge pt = (PassiveEdge)mother;
if (pt._packed_edges != null)
{
p = pt._packed_edges.Count;
pp = " [" + pt._packed_edges.Select(po => String.Format("#{0:X}", po.Tfs.id)).StringJoin(", ") + "]";
}
}
String md = "";
if (mother is Derived)
{
Derived dpe = (Derived)mother;
md = dpe.ChartDaughters.Select(po => String.Format("#{0:X}", po.Tfs.id)).StringJoin(", ");
}
return String.Format("{0:X} #{1:X} [{2}] peers: {3}{4} dtrs: {5} [{6}]",
GetHashCode() & 0xFFFF,
mother.Tfs.id,
md,
p,
pp,
daughters.Length,
daughters.Select(d => String.Format("{0:X}", d.GetHashCode() & 0xFFFF)).StringJoin(", "));
}
};
#endif
};
abstract public unsafe partial class ChartBase : ISysObj, IEnumerable<IParseObj>
{
#if DEBUG
public void CheckDuplicateDerivations()
{
ConcurrentHashSet<ulong> d_hashes = new ConcurrentHashSet<ulong>();
int c_derivations = 0;
foreach (var drv in ((ParseChart)this).AllDerivations)
{
d_hashes.Add(drv.DerivationHash);
c_derivations++;
}
if (c_derivations != d_hashes.Count)
{
//throw new Exception(String.Format("{0} duplicate derivations", c_derivations - d_hashes.Count));
var grps = ((ParseChart)this).AllDerivations.GroupBy(drv => drv.DerivationHash).Where(grp => grp.Count() > 1);
Console.WriteLine(String.Format("{0} duplicate derivations in {1} groups", c_derivations - d_hashes.Count, grps.Count()));
List<String> l0 = new List<String>(), l1 = new List<String>();
foreach (var grp in grps)
{
l0.Add(grp.ElementAt(0).TreeDisplay());
l1.Add(grp.ElementAt(1).TreeDisplay());
System.IO.File.WriteAllLines(String.Format("000.tfs-dump"), l0);
System.IO.File.WriteAllLines(String.Format("001.tfs-dump"), l1);
Console.WriteLine("=========================");
foreach (var drv in grp)
{
Console.WriteLine("{0}", drv.TreeDisplay());
Console.WriteLine();
}
}
}
//if (rgdrv != null)
//{
// if (rgdrv.Count != hsdrv.Count)
// report.AppendLine(String.Format("derivations: {0} --- distinct: {1} (extra {2})", rgdrv.Count, hsdrv.Count, rgdrv.Count - hsdrv.Count));
//}
}
public IEnumerable<PassiveEdge.Derived> AllDerivedEdges()
{
var e = new ChartCell._enum_all_edges(this);
while (e.MoveNext())
{
PassiveEdge.Derived dpe = e.Current as PassiveEdge.Derived;
if (dpe != null)
yield return dpe;
}
}
internal IEnumerable<PassiveEdge.Derived> OrphanEdges()
{
var ade = AllDerivedEdges();
return ade.Except(ade.SelectMany(dce => dce.ChartDaughters.OfType<PassiveEdge.Derived>()));
}
public IEnumerable<PassiveEdge.Derived> DerivationTopEdges()
{
return OrphanEdges().OfType<PassiveEdge.Derived>();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// DEBUG CODE FOLLOWS
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void ChartEdgeReport(IParseObj ce)
{
String span_color = ce.TokenSpan == EntireSpan ? "$yellow" : "$darkyellow";
String sis = SequenceControl.ToString(ce);
PassiveEdge.Derived dce = ce as PassiveEdge.Derived;
TextWriter debug_output = dce.ctrl.config.system.tw_debug;
if (dce == null)
{
debug_output.WriteLineColor("$darkcyan {0,-18} $green E{2,-4} " + span_color + " {3,-7} $green {4}",
ce.GetType().Name,
null,
sis,
ce.TokenSpan,
ce.Tfs);
}
else
{
String fedge = dce.Tfs.ToString();
String medge = fedge.Replace("@", "$green @").Replace("…", "…$darkgreen ");
debug_output.WriteLineColor(new String(' ', 25) + span_color + " {0,-7} $darkgreen {1}$ added by $darkgreen {2}$ is now $darkcyan {3}$ $green E{4,-4}",
dce.TokenSpan,
medge.PadRight(35 + (medge.Length - fedge.Length)),
dce.ChartDaughters.Select(de => String.Format("{0}", de.ToString())).StringJoin("$ + $darkgreen ").PadLeft(9 + (dce.ChartDaughters.Count() - 1) * 12),
dce.GetType().Name,
sis);
}
}
public void DumpChart(String html_out_file)
{
var derivations = DerivationTopEdges()
.Select((de, ix) => new { top = de, ix, de.DescendantsAndSelf });
var edge_lookup = derivations
.SelectMany(dv => dv.DescendantsAndSelf.Select(e => new { top = dv, dv.ix, e }))
.ToLookup(de => de.e, de => new { de.ix, de.top });
StringBuilder sb1 = new StringBuilder();
foreach (var derivation in derivations)
{
sb1.AppendFormat(@"
.dv{0}
{{
}}", derivation.ix);
}
StringBuilder sb = new StringBuilder();
sb.AppendFormat(@"
<html>
<head>
<style>
body
{{
font-family:Arial;
}}
span
{{
cursor: pointer;
}}
.fill
{{
background-color:#f0f0f0;
}}
table tr td
{{
vertical-align:top;
font-size:smaller;
}}
{0}
</style>
</head>
<body>
", sb1.ToString());
int c = ColumnCount;
double grid_cells_x = 120;// Enumerable.Range(1, c - 1).LeastCommonMultiple();
sb.Append("<table border=1><tr>");
int cx_total = 0;
for (int j = 0; j < c; j++)
{
int cx = (int)Math.Round(grid_cells_x * (j + 1) / c) - cx_total;
cx_total += cx;
sb.AppendFormat("<th colspan={0}>{1}</th>\r\n", cx, j);
}
sb.Append("</tr>\r\n\r\n");
var dict = this._GroupBy(e => e.TokenSpan.Length)
.ToDictionary(g => g.Key, g => g.ToLookup(e => e.TokenSpan.StartIndex));
for (int span = c; span > 0; span--)
{
sb.Append("<tr>\r\n");
ILookup<int, IParseObj> length_starts_map;
if (dict.TryGetValue(span, out length_starts_map))
{
cx_total = 0;
int items = c - span + 1;
for (int k = 0; k < items; k++)
{
int cx = (int)Math.Round(grid_cells_x * (k + 1) / items) - cx_total;
cx_total += cx;
IEnumerable<IParseObj> edges = length_starts_map[k];
String s_cont;
if (edges != null && edges.Any())
{
StringBuilder content = new StringBuilder();
foreach (IParseObj pe in edges)
{
String kk = edge_lookup[pe].Select(a => String.Format("dv{0}", a.ix)).StringJoin(" ");
String b = pe is PassiveEdge.Completed ? "style='font-weight:bold;' " : String.Empty;
content.AppendFormat("\t<span {0}class='{1}'>{2}</span><br />\r\n", b, kk, pe.ToString().Replace("-", "‑"));
}
s_cont = content.ToString();
}
else
s_cont = " ";
sb.AppendFormat("\t<td colspan='{0}'>\r\n{1}</td>\r\n", cx, s_cont);
}
}
sb.Append("</tr>\r\n");
}
sb.AppendFormat("</table>");
sb.Append(@"
<script type='text/javascript'>
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
if (document.styleSheets) {
for (var i = 0; i < document.styleSheets.length; i++) {
var styleSheet = document.styleSheets[i];
var ii = 0;
var cssRule = null;
do {
if (styleSheet.cssRules) {
cssRule = styleSheet.cssRules[ii];
} else {
cssRule = styleSheet.rules[ii];
}
if (cssRule) {
if (cssRule.selectorText.toLowerCase() == ruleName) {
return cssRule;
}
}
ii++;
} while (cssRule)
}
}
return null;
}
function ms_in(e) {
var x = e.className.split(' ');
for (var z = 0; z < x.length; z++) {
var r = getCSSRule('.' + x[z]);
if (r != null)
r.style.color = 'red';
}
}
function ms_out(e) {
var x = e.className.split(' ');
for (var z = 0; z < x.length; z++) {
var r = getCSSRule('.' + x[z]);
if (r != null)
r.style.color = 'black';
}
}
var obj = document.getElementsByTagName('span'), o, i = 0;
while (o = obj[i++]) {
o.onmouseover = function() { ms_in(this); };
o.onmouseout = function() { ms_out(this); };
}
</script>
");
sb.AppendFormat("</body></html>");
File.WriteAllText(html_out_file, sb.ToString());
}
#else
public void ChartEdgeReport(IParseObj ce) { }
public void DumpChart(String html_out_file) { }
#endif
};
}