210 lines
6.7 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|