public CYKTable(A[] word, PerformanceCFG cfg) { this.word = word; this.cfg = cfg; InitializeCykTable(); CalculateEpsilonSymbols(); if (word.Length > 0) { FillTable(); } }
/// <summary> /// builds a filled CYK-table out of the cfg /// </summary> /// <param name="word"></param> /// <param name="cfg">cfg in 2NF</param> public CYKTable(A[] word, ContextFreeGrammar cfg) { this.word = word; this.cfg = new PerformanceCFG(cfg); InitializeCykTable(); CalculateEpsilonSymbols(); if (word.Length > 0) { FillTable(); } }
private static void AddChainAndEpsilonEntriesForNextEntry(Dictionary <int, DerivationNode <A> > entries, PerformanceCFG cfg, Dictionary <int, DerivationNode <A> > epsilonSymbols, Queue <DerivationNode <A> > newEntries) { var next = newEntries.Dequeue(); var productionsWithNextOnRightHandsSide = cfg.GetProductionsWhereRightHandSideContains(next.Symbol); foreach (var prod in productionsWithNextOnRightHandsSide) { //only add new entries; so maybe not all derivations are found, but only one is needed if (!entries.ContainsKey(prod.Lhs.UnqiueId)) { AddChainAndEpsilonEntriesForProduction(entries, epsilonSymbols, newEntries, next, prod); } } }
/// <summary> /// adds to the given dictionary recursively all entries, that have a production with only epsilon-symbols on the right hand side, except exactly one of the symbols in entries /// </summary> /// <param name="entries"></param> /// <param name="cfg"></param> /// <param name="epsilonSymbols">symbols, that can reach epsilon without derivate a letter</param> internal static void AddChainAndEpsilonEntries(Dictionary <int, DerivationNode <A> > entries, PerformanceCFG cfg, Dictionary <int, DerivationNode <A> > epsilonSymbols) { var newEntries = new Queue <DerivationNode <A> >(entries.Values); while (newEntries.Count > 0) { AddChainAndEpsilonEntriesForNextEntry(entries, cfg, epsilonSymbols, newEntries); } }
/// <summary> /// creats an entry for the given CYK-table at the defined position /// </summary> /// <param name="cykTable"></param> /// <param name="row"></param> /// <param name="column"></param> /// <param name="epsilonSymbols"></param> /// <param name="cfg"></param> /// <returns></returns> public static TableField <A> CreateTableFieldForCYKTable(TableField <A>[][] cykTable, int row, int column, Dictionary <int, DerivationNode <A> > epsilonSymbols, PerformanceCFG cfg) { var entries = new Dictionary <int, DerivationNode <A> >(); for (int i = 0; i < row; i++) { CombineTwoTableFields(entries, cykTable[i][column], cykTable[row - i - 1][column + i + 1], epsilonSymbols, cfg); } return(new TableField <A>(entries, epsilonSymbols, cfg)); }
private static void CombineTwoTableFields(Dictionary <int, DerivationNode <A> > entries, TableField <A> left, TableField <A> right, Dictionary <int, DerivationNode <A> > epsilonSymbols, PerformanceCFG cfg) { foreach (var prod in cfg.BinaryProductions) { if (left.Entries.TryGetValue(prod.Rhs[0].UnqiueId, out DerivationNode <A> leftNode)) { if (right.Entries.TryGetValue(prod.Rhs[1].UnqiueId, out DerivationNode <A> rightNode)) { if (!entries.ContainsKey(prod.Lhs.UnqiueId)) { entries.Add(prod.Lhs.UnqiueId, new DerivationNode <A>(prod, new List <DerivationNode <A> >() { leftNode, rightNode })); } } } } }
/// <summary> /// creates an entry with a single terminal /// </summary> /// <param name="terminal"></param> /// <param name="epsilonSymbols"></param> /// <param name="cfg"></param> /// <returns></returns> public static TableField <A> WithTerminal(Exprinal <A> terminal, Dictionary <int, DerivationNode <A> > epsilonSymbols, PerformanceCFG cfg) { var entries = new Dictionary <int, DerivationNode <A> > { { terminal.UnqiueId, new DerivationNode <A>(terminal) } }; return(new TableField <A>(entries, epsilonSymbols, cfg)); }
private TableField(Dictionary <int, DerivationNode <A> > entries, Dictionary <int, DerivationNode <A> > epsilonSymbols, PerformanceCFG cfg) { Entries = entries; CFGChainExtender <A> .AddChainAndEpsilonEntries(entries, cfg, epsilonSymbols); }