public Productions <SYMBOL_ENUM, TREE_NODE> GetProductions( SYMBOL_ENUM eofSymbol, SYMBOL_ENUM syntaxErrorSymbol, GrammarReport <SYMBOL_ENUM, TREE_NODE> report) { return(Productions <SYMBOL_ENUM, TREE_NODE> .Create(symbolsRep, productions, eofSymbol, syntaxErrorSymbol, report)); }
public static Productions <SYMBOL_ENUM, TREE_NODE> Create( StringRep <SYMBOL_ENUM> symbolsRep, IEnumerable <Production <SYMBOL_ENUM, TREE_NODE> > productions, SYMBOL_ENUM eofSymbol, SYMBOL_ENUM syntaxErrorSymbol, GrammarReport <SYMBOL_ENUM, TREE_NODE> report) { try { if (ExperimentsSettings.UnfoldingAliases_EXPLOSION) { productions = unfoldIdentityProductions(symbolsRep, productions, eofSymbol, syntaxErrorSymbol); } if (ExperimentsSettings.UnfoldErrorProductions_NOT_USED) { productions = unfoldErrorProductions_NOT_USED(symbolsRep, productions, eofSymbol, syntaxErrorSymbol); } var result = new Productions <SYMBOL_ENUM, TREE_NODE>(symbolsRep, productions, eofSymbol, syntaxErrorSymbol, s => report.AddWarning(s)); return(result); } catch (Exception ex) { report.AddError(new GrammarError(ex.Message)); return(null); } }
CreateActionTable <SYMBOL_ENUM, TREE_NODE>(Productions <SYMBOL_ENUM, TREE_NODE> productions, PrecedenceTable <SYMBOL_ENUM> precedenceTable, GrammarReport <SYMBOL_ENUM, TREE_NODE> report, int lookaheadWidth) where SYMBOL_ENUM : struct where TREE_NODE : class { if (productions == null) { return(null); } if (lookaheadWidth < 1) { throw new ArgumentException("Lookahead width is too small"); } precedenceTable.Validate(lookaheadWidth); BuilderSets <SYMBOL_ENUM, TREE_NODE> builder_sets = BuilderSets.Create(productions, lookaheadWidth); report.Setup(productions, builder_sets); { IEnumerable <Tuple <SYMBOL_ENUM, bool> > err_recur_lhs = productions.Entries // do not check Auto recursive .Where(prod => ((prod.Recursive == RecursiveEnum.No) && builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal)) || ((prod.Recursive == RecursiveEnum.Yes) && !builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal))) .Select(prod => Tuple.Create(prod.LhsNonTerminal, !builder_sets.CoverSets.IsRecursive(prod.LhsNonTerminal))).Distinct().ToArray(); if (err_recur_lhs.Any()) { if (err_recur_lhs.Where(it => it.Item2).Any()) { report.AddError("Productions incorrectly marked as recursive: " + err_recur_lhs.Where(it => it.Item2).Select(it => "\"" + productions.SymbolsRep.Get(it.Item1) + "\"").Join(",") + "."); } if (err_recur_lhs.Where(it => !it.Item2).Any()) { report.AddError("Productions incorrectly marked as non-recursive: " + err_recur_lhs.Where(it => !it.Item2).Select(it => "\"" + productions.SymbolsRep.Get(it.Item1) + "\"").Join(",") + "."); } return(null); } } Dfa <SYMBOL_ENUM, TREE_NODE> dfa = Worker.CreateDfa(productions, lookaheadWidth, builder_sets.PrecomputedRhsFirsts, builder_sets.HorizonSets); report.Setup(dfa); return(new ActionBuilder <SYMBOL_ENUM, TREE_NODE>().FillActionTable(productions, builder_sets.FirstSets, builder_sets.CoverSets, builder_sets.HorizonSets, lookaheadWidth, dfa, precedenceTable, report)); }
Create <SYMBOL_ENUM, TREE_NODE>(Productions <SYMBOL_ENUM, TREE_NODE> productions, PrecedenceTable <SYMBOL_ENUM> precedenceTable, GrammarReport <SYMBOL_ENUM, TREE_NODE> report, int lookaheadWidth) where SYMBOL_ENUM : struct where TREE_NODE : class { ActionTable <SYMBOL_ENUM, TREE_NODE> action_table = CreateActionTable(productions, precedenceTable, report, lookaheadWidth); if (action_table == null) { return(null); } else { return(new Parser <SYMBOL_ENUM, TREE_NODE>(action_table, productions.SymbolsRep)); } }
public ActionTable <SYMBOL_ENUM, TREE_NODE> FillActionTable(Productions <SYMBOL_ENUM, TREE_NODE> productions, FirstSets <SYMBOL_ENUM> firstSets, CoverSets <SYMBOL_ENUM> coverSets, HorizonSets <SYMBOL_ENUM> horizonSets, int lookaheadWidth, Dfa <SYMBOL_ENUM, TREE_NODE> dfa, PrecedenceTable <SYMBOL_ENUM> precedenceTable, GrammarReport <SYMBOL_ENUM, TREE_NODE> report) { this.coverSets = coverSets; this.horizonSets = horizonSets; this.report = report; this.precedenceTable = precedenceTable ?? new PrecedenceTable <SYMBOL_ENUM>(productions.SymbolsRep); this.symbolsRep = productions.SymbolsRep; actionTable = new ActionTable <SYMBOL_ENUM, TREE_NODE>(dfa, productions, lookaheadWidth); foreach (Node <SYMBOL_ENUM, TREE_NODE> node in dfa.Nodes) { foreach (SymbolChunk <SYMBOL_ENUM> chunk in node.State.PossibleInputs) { ParseAction <SYMBOL_ENUM, TREE_NODE> action_data = computeAction(node, chunk); if (!report.HasGrammarErrors) { actionTable.Add(node.State.Index, chunk, new[] { action_data }); } } // checking recovery conflicts IEnumerable <SingleState <SYMBOL_ENUM, TREE_NODE> > recovery_items = node.State.ParsingActiveItems .Where(it => it.IsAtRecoveryPoint); var recovery_stats = DynamicDictionary.CreateWithDefault <SYMBOL_ENUM, List <SingleState <SYMBOL_ENUM, TREE_NODE> > >(); foreach (SingleState <SYMBOL_ENUM, TREE_NODE> rec_state in recovery_items) { foreach (SymbolChunk <SYMBOL_ENUM> first in firstSets[rec_state.RecoveryMarkerSymbol].Chunks) { recovery_stats[first.Symbols.First()].Add(rec_state); } } foreach (var pair in recovery_stats.Where(it => it.Value.Count > 1)) { report.AddError(pair.Value.Select(it => it.IndexStr), "Recovery item conflict on \"" + symbolsRep.Get(pair.Key) + "\"."); } } report.AddWarnings(precedenceTable.GetUnusedEntries(symbolsRep)); if (report.HasGrammarErrors) { return(null); } else { report.ActionTable = actionTable; return(actionTable); } }