Files
libremetaverse/LibreMetaverse.LslTools/Tools/Transition.cs
2024-06-30 16:49:51 -05:00

210 lines
6.7 KiB
C#

/*
* Copyright (c) 2019-2024, Sjofn LLC
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the openmetaverse.co nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
namespace LibreMetaverse.LslTools
{
public class Transition
{
public Hashtable m_reduce = new Hashtable();
private Hashtable m_reads = new Hashtable();
private Hashtable m_includes = new Hashtable();
internal Hashtable m_lookbackOf = new Hashtable();
public int m_tno;
public ParseState m_ps;
public CSymbol m_A;
public ParserShift m_next;
private SymbolSet m_DR;
private SymbolSet m_Read;
private SymbolSet m_Follow;
public Transition(ParseState p, CSymbol a)
{
this.m_ps = p;
this.m_A = a;
this.m_tno = p.m_sgen.m_trans++;
p.m_transitions[(object) a.yytext] = (object) this;
}
private ParsingInfo ParsingInfo => this.m_ps.m_sgen.m_symbols.GetSymbolInfo(this.m_A.yytext, this.m_A.m_yynum);
public static Hashtable reads(Transition a)
{
return a.m_reads;
}
public static Hashtable includes(Transition a)
{
return a.m_includes;
}
public static SymbolSet DR(Transition a)
{
return a.m_DR;
}
public static SymbolSet Read(Transition a)
{
return a.m_Read;
}
public static SymbolSet Follow(Transition a)
{
return a.m_Follow;
}
public static void AddToRead(Transition a, SymbolSet s)
{
a.m_Read.Add(s);
}
public static void AddToFollow(Transition a, SymbolSet s)
{
a.m_Follow.Add(s);
}
public static void BuildDR(Transition t)
{
SymbolsGen sgen = t.m_ps.m_sgen;
t.m_DR = new SymbolSet(sgen);
if (t.m_next == null)
return;
foreach (Transition transition in (IEnumerable) t.m_next.m_next.m_transitions.Values)
{
if (transition.m_next != null && (transition.m_A.m_symtype == CSymbol.SymType.terminal || transition.m_A.m_symtype == CSymbol.SymType.eofsymbol))
t.m_DR.AddIn(transition.m_A);
}
}
public static void Final(Transition t)
{
t.m_DR.AddIn(t.m_ps.m_sgen.m_symbols.EOFSymbol);
}
public static void BuildReads(Transition t)
{
t.m_Read = new SymbolSet(t.m_ps.m_sgen);
ParseState parseState = t.m_A.Next(t.m_ps);
if (parseState == null)
return;
foreach (Transition transition in (IEnumerable) parseState.m_transitions.Values)
{
if (transition.m_A.IsNullable())
t.m_reads[(object) transition] = (object) true;
}
}
public static void BuildIncludes(Transition t)
{
t.m_Follow = new SymbolSet(t.m_ps.m_sgen);
foreach (Production prod in t.m_A.m_prods)
{
for (int i = prod.m_rhs.Count - 1; i >= 0; --i)
{
CSymbol rh = (CSymbol) prod.m_rhs[i];
if (rh.m_symtype == CSymbol.SymType.nonterminal)
((Transition) (i <= 0 ? t.m_ps : new Path(t.m_ps, prod.Prefix(i)).Top).m_transitions[(object) rh.yytext]).m_includes[(object) t] = (object) true;
if (!rh.IsNullable())
break;
}
}
}
public static void BuildLookback(Transition t)
{
foreach (ParserReduce parserReduce in (IEnumerable) t.m_reduce.Values)
parserReduce.BuildLookback(t);
}
public static void BuildLA(Transition t)
{
foreach (ParserReduce key in (IEnumerable) t.m_lookbackOf.Keys)
key.m_lookAhead.Add(t.m_Follow);
}
public static void BuildParseTable(Transition t)
{
YyParser symbols = t.m_ps.m_sgen.m_symbols;
ParsingInfo parsingInfo = t.ParsingInfo;
ParserReduce parserReduce1 = (ParserReduce) null;
foreach (ParserReduce parserReduce2 in (IEnumerable) t.m_reduce.Values)
{
if ((!t.m_ps.m_sgen.m_lalrParser ? (parserReduce2.m_prod.m_lhs.m_follow.Contains(t.m_A) ? 1 : 0) : (parserReduce2.m_lookAhead.Contains(t.m_A) ? 1 : 0)) != 0)
{
if (parserReduce1 != null)
symbols.erh.Error(new CSToolsException(12,
$"reduce/reduce conflict {(object)parserReduce1.m_prod.m_pno} vs {(object)parserReduce2.m_prod.m_pno}" +
$" state {(object)t.m_ps.m_state} on {(object)t.m_A.yytext}"));
parserReduce1 = parserReduce2;
}
}
if (t.m_next != null && t.m_A != symbols.EOFSymbol)
{
if (parserReduce1 == null)
{
parsingInfo.m_parsetable[(object) t.m_ps.m_state] = (object) t.m_next;
}
else
{
switch (t.m_A.ShiftPrecedence(parserReduce1.m_prod, t.m_ps))
{
case Precedence.PrecType.left:
parsingInfo.m_parsetable[(object) t.m_ps.m_state] = (object) t.m_next;
break;
case Precedence.PrecType.right:
parsingInfo.m_parsetable[(object) t.m_ps.m_state] = (object) parserReduce1;
break;
}
}
}
else
{
if (parserReduce1 == null)
return;
parsingInfo.m_parsetable[(object) t.m_ps.m_state] = (object) parserReduce1;
}
}
public void Print0()
{
Console.Write(" " + this.m_A.yytext);
if (this.m_next != null)
Console.Write(" shift " + (object) this.m_next.m_next.m_state);
foreach (Production key in (IEnumerable) this.m_reduce.Keys)
Console.Write(" reduce (" + (object) key.m_pno + ")");
Console.WriteLine();
}
public void Print(SymbolSet x, string s)
{
Console.Write("Transition (" + (object) this.m_ps.m_state + "," + this.m_A.yytext + ") " + s + " ");
x.Print();
}
}
}