public Rule(ParseAction action, Symbol symbol, int srcId, int?destId = null) { Action = action; Symbol = symbol; SrcId = srcId; DestId = destId; }
public (Item?, ParseAction) FindTransitionOfItemOn(Item item, Symbol symbol) { var(target, action) = FindTransitionOfItemOnUnchecked(item, symbol); return(TransitionIsValidForItem(action, item, symbol) ? (target, action) : (null, ParseAction.MakeDiscard())); }
private bool TransitionIsValidForItem(ParseAction action, Item item, Symbol inputSymbol) { /* * Constraints: * - If the action is to discard, then this is fine. * - If precedence(lhs) < precedence(rhs), this must be a shift * - If precedence(lhs) > precedence(rhs) and dot is at the end, this must be a reduce * - If either has undefined precedence or associativity, then this is ok * - If precedence(rhs) == precedence(lhs), * - If either are left-associative and dot is at the end, this must be a reduce * - Otherwise, this must be a shift */ var lhsIdx = Array.FindLastIndex(item.Production.Ingredients, HasPrecedence); var lhs = item.Production.OverridePrecedence ?? (lhsIdx != -1 ? item.Production.Ingredients[lhsIdx] : (Symbol?)null); var rhs = inputSymbol; var pLeft = PrecedenceOf(lhs); var pRight = PrecedenceOf(rhs); var aLeft = AssociativityOf(lhs); var aRight = AssociativityOf(rhs); if (pLeft < pRight && action.Type != ParseActionType.Shift) { return(false); } if (pLeft > pRight && item.CanReduce && action.Type != ParseActionType.Reduce) { return(false); } if (pLeft is null || pRight is null || aLeft == Associativity.Default || aRight == Associativity.Default) { return(true); } if (pLeft == pRight) { Debug.Assert(aLeft == aRight); if (aLeft == Associativity.Left || aRight == Associativity.Left) { if (item.CanReduce && action.Type != ParseActionType.Reduce) { return(false); } } else if (action.Type != ParseActionType.Shift) { return(false); } } return(true); }
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()); }
public Entry(ParseAction action, int?destStateId = null) { Action = action; mDestStateId = destStateId; }