private DotState[] BuildLr0ItemSets() { var result = new List <DotState>(); var initialItemSet = ClosureLr0(new MutableDotItemSet { new DotItem(grammar.AugmentedProduction, 0) { LA = TokenSet.Mutable() } }); result.Add(new DotState(0, initialItemSet)); bool addedStatesInRound; do { addedStatesInRound = false; for (int i = 0; i != result.Count; ++i) { var itemSet = result[i].Items; foreach (var token in GetOutTokens(itemSet)) { var nextStateItems = GoTo(itemSet, token); CollectClosureLookaheads(nextStateItems, grammar); if (nextStateItems.Count == 0) { throw new InvalidOperationException("Internal error: next state cannot be empty"); } var nextState = result.Find(state => state.Items.Equals(nextStateItems)); if (nextState == null) { addedStatesInRound = true; nextState = new DotState(result.Count, nextStateItems); result.Add(nextState); } if (result[i].AddTransition(token, nextState, TokenSet)) { addedStatesInRound = true; } } } }while (addedStatesInRound); StateSet = new BitSetType(result.Count); return(result.ToArray()); }
public bool AddTransition(int token, DotState to, IntSetType tokenSetType) { bool result; var existing = Transitions.FirstOrDefault(t => t.To == to); if (existing == null) { existing = new DotTransition(tokenSetType.Mutable(), to); Transitions.Add(existing); result = true; } else { result = !existing.Tokens.Contains(token); } existing.Tokens.Add(token); return(result); }
private bool IsValueOnlyEpsilonReduceItem(DotItem item, DotState state, int lookahead) { if (item.Position != 0 || grammar.IsStartProduction(item.ProductionId) || !grammar.IsTailNullable(item) || !item.LA.Contains(lookahead)) { return(false); } int epsilonToken = item.Outcome; foreach (var parentItem in state.Items) { if (parentItem == item) { continue; } if (parentItem.NextToken == epsilonToken) { if (!grammar.IsTailNullable(parentItem)) { // there is at least one rule which needs shift on epsilonToken return(false); } if (grammar.HasFirst(parentItem.CreateNextItem(), lookahead)) { // One of the subseqent non-terms in parentItem can start parsing with current lookahead. // It means that we need tested epsilonToken production for continue parsing on parentItem. return(false); } } } return(true); }
public DotTransition(MutableIntSet tokens, DotState to) { this.Tokens = tokens; this.To = to; }