private (Item?, ParseAction) FindTransitionOfItemOnUnchecked(Item item, Symbol symbol) { var productionLen = item.Production.Ingredients.Length; if (item.DotPos < productionLen && symbol == item.Production.Ingredients[item.DotPos]) { return(item.ShiftedByOne(), ParseAction.MakeShift()); } if (item.DotPos >= productionLen && symbol == item.Follow) { if (symbol == Symbol.EndOfInput && item.Production.Product == Symbol.ExtendedStartSymbol) { return(null, ParseAction.MakeAccept()); } return(null, ParseAction.MakeReduce(item.Production)); } return(null, ParseAction.MakeDiscard()); }
public ParseAction TransitionedOn(Symbol symbol, out ParserState?targetState) { var items = Expand(); var transitions = new HashSet <Transition>(); foreach (var item in items) { var(target, action) = mCfg.FindTransitionOfItemOn(item, symbol); if (action.Type == ParseActionType.Discard) { continue; } var transition = new Transition(action, item, target); transitions.Add(transition); } if (transitions.Count == 0) { targetState = null; return(ParseAction.MakeReject()); } if (transitions.Any(t => t.Action.Type == ParseActionType.Accept)) { targetState = null; return(ParseAction.MakeAccept()); } if (transitions.Any(t => t.Action.Type == ParseActionType.Reduce && ( mCfg.AssociativityOf(t.Action.Production) == Associativity.Left || mCfg.PrecedenceOf(t.Action.Production) > mCfg.PrecedenceOf(symbol)))) { transitions.RemoveWhere(t => t.Action.Type != ParseActionType.Reduce); if (transitions.Count > 1) { throw new Exception("There is a reduce-reduce conflict."); } targetState = null; return(ParseAction.MakeReduce(transitions.First().Action.Production)); } if (transitions.All(t => t.Action.Type == ParseActionType.Reduce)) { if (transitions.Count > 1) { throw new Exception("There is a reduce-reduce conflict."); } targetState = null; return(ParseAction.MakeReduce(transitions.First().Action.Production)); } transitions.RemoveWhere(t => t.Action.Type != ParseActionType.Shift); if (transitions.Count == 0) { targetState = null; return(ParseAction.MakeReject()); } targetState = new ParserState( mCfg, transitions .Select(t => t.Dest ?? throw new NullReferenceException()) .ToHashSet()); return(ParseAction.MakeShift()); }