private void ComputeIncludes() { // (p,A) include (q,B) iff B -> Beta A Gamma and Gamma => empty and q -> Beta -> p foreach (AutomatonState q in states) { foreach (Transition qB in q.nonTerminalTransitions.Values) { foreach (Production prod in qB.A.productions) { for (int i = prod.rhs.Count - 1; i >= 0; i--) { Symbol A = prod.rhs[i]; NonTerminal NT = A as NonTerminal; if (NT != null) { AutomatonState p = PathTo(q, prod, i); p.nonTerminalTransitions[NT].includes.Add(qB); } if (!A.IsNullable()) { break; } } } } } }
private static int GetDefaultAction(AutomatonState state) { if (state.ForceLookahead) { return(0); } IEnumerator <ParserAction> enumerator = state.parseTable.Values.GetEnumerator(); enumerator.MoveNext(); int defaultAction = enumerator.Current.ToNum(); if (defaultAction > 0) { return(0); // can't have default shift action } foreach (KeyValuePair <Terminal, ParserAction> transition in state.parseTable) { if (transition.Value.ToNum() != defaultAction) { return(0); } } return(defaultAction); }
internal ReduceReduceConflict(Terminal sy, string s1, string s2, int prod, AutomatonState state) : base(sy, s1, s2) { chosen = prod; inState = state; state.Link(this); }
internal void AddPredecessor(AutomatonState pred) { if (predecessors == null) { predecessors = new List <AutomatonState>(); } if (!predecessors.Contains(pred)) { predecessors.Add(pred); } }
private static void GenerateShiftReduceMachineState(int stateNumber, AutomatonState state) { Console.Write(" states[{0}] = new State(", stateNumber); int defaultAction = GetDefaultAction(state); if (defaultAction != 0) { // // Having a default action happens if the LR0 machine // has a Reduce action, that is, no lookahead is needed. // Console.Write(defaultAction); } else { // // Otherwise, we have an action that depends on the // lookahead, determined by the LALR(1) automaton. // Console.Write("new int[]{"); bool first = true; foreach (KeyValuePair <Terminal, ParserAction> transition in state.parseTable) { if (!first) { Console.Write(","); } Console.Write("{0},{1}", transition.Key.num, transition.Value.ToNum()); first = false; } Console.Write('}'); } if (state.nonTerminalTransitions.Count > 0) { // // The Goto table is needed if there are non-terminal transitions. // Console.Write(",new int[]{"); bool first = true; foreach (Transition transition in state.nonTerminalTransitions.Values) { if (!first) { Console.Write(","); } Console.Write("{0},{1}", transition.A.num, transition.next.num); first = false; } Console.Write('}'); } Console.WriteLine(");"); }
static string KernelToString(AutomatonState thisState) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); builder.AppendLine(); builder.AppendLine(Header2("Kernel Items")); foreach (ProductionItem item in thisState.kernelItems) { builder.AppendFormat(" {0}", ItemToString(item, true)); builder.AppendLine(); } return(builder.ToString()); }
private void ExpandState(Symbol sym, AutomatonState newState) { //newState.accessedBy = sym; states.Add(newState); if (!accessedBy.ContainsKey(sym)) { accessedBy[sym] = new List <AutomatonState>(); } accessedBy[sym].Add(newState); newState.AddClosure(); ComputeGoto(newState); }
internal void AddGoto(Symbol s, AutomatonState next) { this.Goto[s] = next; Terminal term; if ((term = s as Terminal) != null) { terminalTransitions.Add(term); } else { NonTerminal nonTerm = (NonTerminal)s; nonTerminalTransitions.Add(nonTerm, new Transition(nonTerm, next)); } }
internal static void PopulatePrefixes(List <AutomatonState> states) { AutomatonState start = states[0]; start.shortestPrefix = new List <Symbol>(); // The empty list. start.statePath = new List <AutomatonState>(); start.statePath.Add(start); bool changed = false; do { changed = false; foreach (AutomatonState state in states) { List <Symbol> newfix; List <Symbol> prefix = state.shortestPrefix; List <AutomatonState> newPath; List <AutomatonState> oldPath = state.statePath; if (prefix != null) { foreach (KeyValuePair <Symbol, AutomatonState> a in state.Goto) { Symbol smbl = a.Key; AutomatonState nextState = a.Value; newfix = ListClone <Symbol>(prefix); newPath = ListClone <AutomatonState>(oldPath); newPath.Add(nextState); if (!smbl.IsNullable()) { newfix.Add(smbl); } if (nextState.shortestPrefix == null || nextState.shortestPrefix.Count > newfix.Count) { nextState.shortestPrefix = newfix; nextState.statePath = newPath; changed = true; } } } } } while (changed); }
private static AutomatonState PathTo(AutomatonState q, Production prod, int prefix) { // q -> prod.rhs[0] ... prod.rhs[prefix] -> ??? for (int i = 0; i < prefix; i++) { Symbol s = prod.rhs[i]; if (q.Goto.ContainsKey(s)) { q = q.Goto[s]; } else { return(null); } } return(q); }
private void ComputeGoto(AutomatonState state) { foreach (ProductionItem item in state.allItems) { if (!item.expanded && !item.isReduction()) { item.expanded = true; Symbol s1 = item.production.rhs[item.pos]; // Create itemset for new state ... List <ProductionItem> itemSet = new List <ProductionItem>(); itemSet.Add(new ProductionItem(item.production, item.pos + 1)); foreach (ProductionItem item2 in state.allItems) { if (!item2.expanded && !item2.isReduction()) { Symbol s2 = item2.production.rhs[item2.pos]; if (s1 == s2) { item2.expanded = true; itemSet.Add(new ProductionItem(item2.production, item2.pos + 1)); } } } AutomatonState existingState = FindExistingState(s1, itemSet); if (existingState == null) { AutomatonState newState = new AutomatonState(itemSet); state.AddGoto(s1, newState); ExpandState(s1, newState); } else { state.AddGoto(s1, existingState); } } } }
static string StateToString(AutomatonState thisState) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); //builder.AppendLine(Header2("Kernel Items")); //foreach (ProductionItem item in thisState.kernelItems) //{ // builder.AppendFormat(" {0}", ItemToString(item, true)); // builder.AppendLine(); //} //builder.AppendLine(); if (thisState.parseTable.Count > 0) { builder.AppendLine(Header2("Parser Actions")); } foreach (KeyValuePair <Terminal, ParserAction> a in thisState.parseTable) { builder.AppendFormat(" {0,-14} {1}", a.Key, ActionToString(a.Value)); builder.AppendLine(); } builder.AppendLine(); if (thisState.nonTerminalTransitions.Count > 0) { builder.AppendLine(Header2("Transitions")); } foreach (KeyValuePair <NonTerminal, Transition> n in thisState.nonTerminalTransitions) { builder.AppendFormat(" {0,-14} go to state {1}", n.Key, StateRef(thisState.Goto[n.Key].num)); builder.AppendLine(); } builder.AppendLine(); return(builder.ToString()); }
static void DiagnoseState <T>(StreamWriter writer, AutomatonState state, Mapper <T, AutomatonState> map) { // List<T> statePath = ListUtilities.Map<T, AutomatonState>(state.statePath, map); IEnumerable <T> statePath = ListUtilities.MapC <T, AutomatonState>(state.statePath, map); IEnumerable <T> predList = ListUtilities.MapC <T, AutomatonState>(state.predecessors, map); writer.WriteLine(" Shortest prefix: {0}", ListUtilities.GetStringFromList(state.shortestPrefix, " ", 8)); writer.WriteLine(" Shortest path: {0}", ListUtilities.GetStringFromList(statePath, "->", 19, (ListUtilities.BreakRule) 16)); writer.WriteLine(" Predecessors: {0}", ListUtilities.GetStringFromList(predList, ", ", 18, (ListUtilities.BreakRule) 16)); writer.Write(KernelToString(state)); if (state.conflicts != null) { writer.WriteLine(); writer.WriteLine(" <b>Conflicts in this state</b>"); foreach (Conflict conflict in state.conflicts) { conflict.HtmlReport(writer); } } writer.WriteLine(); }
internal void BuildParseTable() { foreach (AutomatonState state in states) { // // Add shift actions ... // This makes shift the default action for all // terminal transitions. This is modified as required, // later in this foreach state loop. // foreach (Terminal t in state.terminalTransitions) { state.parseTable[t] = new Shift(state.Goto[t]); } // Add reduce actions ... foreach (ProductionItem item in state.allItems) { if (item.isReduction()) { // Accept on everything if (item.production == grammar.rootProduction) { foreach (Terminal t in grammar.terminals.Values) { state.parseTable[t] = new Reduce(item); } } foreach (Terminal t in item.LA) { // possible conflict with existing action if (state.parseTable.ContainsKey(t)) { Reduce reduceAction; ParserAction other = state.parseTable[t]; Production iProd = item.production; if ((reduceAction = other as Reduce) != null) { Production oProd = reduceAction.item.production; // Choose in favour of production listed first in the grammar if (oProd.num > iProd.num) { state.parseTable[t] = new Reduce(item); } string p1 = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", oProd.num, oProd.ToString()); string p2 = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", iProd.num, iProd.ToString()); int chsn = (oProd.num > iProd.num ? iProd.num : oProd.num); grammar.conflicts.Add(new ReduceReduceConflict(t, p1, p2, chsn, state)); if (GPCG.Verbose) { Console.Error.WriteLine( "Reduce/Reduce conflict in state {0} on symbol {1}", state.num, t.ToString()); Console.Error.WriteLine(p1); Console.Error.WriteLine(p2); } else { Console.Error.WriteLine("Reduce/Reduce conflict, state {0}: {1} vs {2} on {3}", state.num, iProd.num, oProd.num, t); } } else { if (iProd.prec != null && t.prec != null) { if (iProd.prec.prec > t.prec.prec) { // // Production iProd has precedence over t, so Reduce. // state.parseTable[t] = new Reduce(item); // No shift/Reduce warning. } else if (iProd.prec.prec == t.prec.prec) { // // Precedence is equal, so use associativity to decide. // if (t.prec.type == PrecType.left) { // // For %left tokens reduce the left subexpression. // state.parseTable[t] = new Reduce(item); } else if (t.prec.type == PrecType.nonassoc) // && iProd.RightmostTerminal() == t) { // What is the correct semantics here? // If %nonassoc x y, is E x E y E an error? // The YACC spec seems to imply, but not explictly state, // that x,y are non-associative AS A GROUP // rather than just individually non-associative. // // For %nonassoc tokens disallow the shift action, and force // lookahead just in case this state has an LR0 Reduce action. // { state.parseTable.Remove(t); state.ForceLookahead = true; } // else t.prec.type == PrecType.right, so Shift. } // else iProd.prec.prec < t.proc.prec, so Shift anyway. } else // Need to issue a Shift/Reduce warning message. { AutomatonState next = ((Shift)other).next; string p1 = String.Format(CultureInfo.InvariantCulture, " Shift \"{0}\":\tState-{1} -> State-{2}", t, state.num, next.num); string p2 = String.Format(CultureInfo.InvariantCulture, " Reduce {0}:\t{1}", iProd.num, iProd.ToString()); grammar.conflicts.Add(new ShiftReduceConflict(t, p1, p2, state, next)); if (GPCG.Verbose) { Console.Error.WriteLine("Shift/Reduce conflict"); Console.Error.WriteLine(p1); Console.Error.WriteLine(p2); } else { Console.Error.WriteLine("Shift/Reduce conflict, state {0} on {1}", state.num, t); } } } } else { state.parseTable[t] = new Reduce(item); } } } } } }
internal ShiftReduceConflict(Terminal sy, string s1, string s2, AutomatonState from, AutomatonState to) : base(sy, s1, s2) { fromState = from; toState = to; fromState.Link(this); }
internal Transition(NonTerminal A, AutomatonState next) { this.A = A; this.next = next; }