private static void AddElement( TProgram program, SymbolTreeNode parent, SymbolTreeNode rootNode, HashSet <SymbolTreeNode> visited) { if (program == null) { return; } if (!parent.Children.ContainsKey(program.Label)) { parent.Children.Add(program.Label, new SymbolTreeNode(program.Label, rootNode)); } var node = parent.Children[program.Label]; if (!visited.Contains(node)) { node.Value++; visited.Add(node); } if (program.Children == null || program.Children.Count == 0) { return; } foreach (var child in program.Children) { AddElement((TProgram)child, node, rootNode, visited); } }
private static uint GetCommonCount(SymbolTreeNode node1, SymbolTreeNode node2) { var commonCount = Math.Min(node1.Value, node2.Value); foreach (var child1 in node1.Children) { if (node2.Children.ContainsKey(child1.Key)) { commonCount += GetCommonCount(child1.Value, node2.Children[child1.Key]); } } return(commonCount); }
private static void Prune(SymbolTreeNode node, uint frequencyThreshold) { if (node.Children == null || node.Children.Count == 0) { return; } var children = node.Children.ToList(); node.Children.Clear(); foreach (var child in children) { if (child.Value.Value < frequencyThreshold) { continue; } node.Children.Add(child); Prune(child.Value, frequencyThreshold); } }
public SymbolTreeNode(string symbol, SymbolTreeNode rootNode) { this._symbol = symbol; this.Children = new Dictionary <string, SymbolTreeNode>(); this.RootNode = rootNode; }
private static uint GetNodeCount(SymbolTreeNode node) { return((uint)(node.Value + node.Children.Values.Sum(child => GetNodeCount(child)))); }
public void applyRules(List <ParseTreeNode> arg_nlist) { #if DEBUG Console.WriteLine("[applyRules] entered."); treeRoot.ShowTree(4, null); Console.WriteLine("Min Required Strokes: " + minRequiredStrokes); Console.WriteLine("Call: " + apply_rule_counter); #else //Console.Write(apply_rule_counter); //Console.Write('\r'); #endif // increment counter apply_rule_counter++; if (arg_nlist.Count == 0) { return; } if (unusedStrokes < 1 && arg_nlist[0] != ParseTreeNode.EndOfBaseline && !(arg_nlist[0] is RelationTreeNode)) { return; } // if ( unusedStrokes > 0 && !( arg_nlist[ 0 ].GetType().Equals( typeof( ParseTreeNode ) ) ) ) return; List <ParseTreeNode> nlist = new List <ParseTreeNode>(arg_nlist); ParseTreeNode n = nlist[0]; nlist.RemoveAt(0); if (n == ParseTreeNode.EndOfBaseline) { // END-OF-BASELINE CASE PartitionResultWrapper pr = attachSymbol(currentSymbol.symbol.lbt, null); // continue only if valid partition made if (pr != null) { if (nlist.Count == 0 && unusedStrokes == 0 && unusedInputStrokes == 0) { #if DEBUG Console.WriteLine("***ACCEPT***"); #endif acceptCurrentParseTree(); } int nodes_added = nlist.Count; if (pr.result != null && pr.result.ABOVE.lbt.strokes.Count != 0) { nlist.Add(pr.result.ABOVE); } if (pr.result != null && pr.result.BELOW.lbt.strokes.Count != 0) { nlist.Add(pr.result.BELOW); } if (pr.result != null && pr.result.CONTAINS.lbt.strokes.Count != 0) { nlist.Add(pr.result.CONTAINS); } if (pr.result != null && pr.result.SUBSC.lbt.strokes.Count != 0) { nlist.Add(pr.result.SUBSC); } if (pr.result != null && pr.result.SUPER.lbt.strokes.Count != 0) { nlist.Add(pr.result.SUPER); } // add BLEFT/TLEFT //if ( pr.result != null && pr.result.BLEFT.lbt.strokes.Count != 0 ) nlist.Add( pr.result.BLEFT ); //if ( pr.result != null && pr.result.TLEFT.lbt.strokes.Count != 0 ) nlist.Add( pr.result.TLEFT ); nodes_added = nlist.Count - nodes_added; minRequiredStrokes += nodes_added; applyRules(nlist); } else { #if DEBUG Console.WriteLine("**BACKTRACK: end-of-baseline, invalid partition"); #endif } } else if (n is RelationTreeNode) { // handle relation nodes by adding new parse tree node RelationTreeNode rtn = n as RelationTreeNode; ParseTreeNode ptn = new ParseTreeNode(); ptn.strokes = rtn.strokes; ptn.nodeType = rtn.nodeType; // increment here for new production ptn.lbt = rtn.lbt; rtn.children.Clear(); // remove all before rtn.children.Add(ptn); parse(ptn.lbt, ptn, nlist); } else if (n.nodeType.StartsWith("*")) { // if n generates terminal symbols List <LexerResult> C = SelectCandidateSymbols(n.nodeType); //candidateSymbols = C; foreach (LexerResult c in C) { PartitionResultWrapper pr = attachSymbol(currentSymbol == null ? initLBT : currentSymbol.symbol.lbt, c); if (pr != null) { pushCurrentState(); // update current state currentSymbol = new PreviousSymbol(c, n, null, null, true); unusedStrokes -= currentSymbol.symbol.segment.strokes.Count; unusedInputStrokes -= currentSymbol.symbol.segment.strokes.Count; // remove one of the min required strokes for the current token minRequiredStrokes -= 1; // prune by number of strokes left if (unusedInputStrokes < minRequiredStrokes) { popCurrentState(); return; // continue; } List <string> layoutClasses = grammar.GetLayoutClassesFromTerminal(c.segment.classification[0].symbol); if (layoutClasses.Count == 0) { continue; } candidateSymbols = new List <LexerResult>(); foreach (string layoutClass in layoutClasses) { List <LexerResult> res = lexer.Next(c.lbt, c.segment, layoutClass, MAX_NEIGHBORS); foreach (LexerResult r in res) { if (!candidateSymbols.Contains(r)) { candidateSymbols.Add(r); } } } if (candidateSymbols.Count == 0 && !nlist.Contains(ParseTreeNode.EndOfBaseline)) { nlist.Insert(0, ParseTreeNode.EndOfBaseline); } // not end of baseline, so prune and backtrack if necessary else if (nlist.Count > 0 && (nlist[0] is RelationTreeNode == false)) { // prune candidates based on the current node type foreach (LexerResult lr in candidateSymbols) { for (int k = 0; k < lr.segment.classification.Count; k++) { if (grammar.NonTerminalCanGenerateTerminal(nlist[0].nodeType, lr.segment.classification[k].symbol) == false) { lr.segment.classification.RemoveAt(k--); } } } // remove candidate symbols which contain no symbol alternatives for (int k = 0; k < candidateSymbols.Count; k++) { if (candidateSymbols[k].segment.classification.Count == 0) { candidateSymbols.RemoveAt(k--); } } // no valid symbols given the grammar, so bbreak out early if (candidateSymbols.Count == 0) { popCurrentState(); return; // continue; } } SymbolTreeNode nc = new SymbolTreeNode(c); n.children.Add(nc); /* * if ( nlist.Count == 0 && unusedStrokes == 0 ) { * if ( unusedInputStrokes == 0 ) acceptCurrentParseTree(); * } else { */ // append relation nodes to the END List <RelationTreeNode> nlist_rels = new List <RelationTreeNode>(); if (pr.result != null && pr.result.ABOVE.lbt.strokes.Count != 0) { nlist_rels.Add(pr.result.ABOVE); } if (pr.result != null && pr.result.BELOW.lbt.strokes.Count != 0) { nlist_rels.Add(pr.result.BELOW); } if (pr.result != null && pr.result.CONTAINS.lbt.strokes.Count != 0) { nlist_rels.Add(pr.result.CONTAINS); } if (pr.result != null && pr.result.SUBSC.lbt.strokes.Count != 0) { nlist_rels.Add(pr.result.SUBSC); } if (pr.result != null && pr.result.SUPER.lbt.strokes.Count != 0) { nlist_rels.Add(pr.result.SUPER); } //if ( pr.result != null && pr.result.BLEFT.lbt.strokes.Count != 0 ) nlist_rels.Add( pr.result.BLEFT ); //if ( pr.result != null && pr.result.TLEFT.lbt.strokes.Count != 0 ) nlist_rels.Add( pr.result.TLEFT ); foreach (RelationTreeNode rtn in nlist_rels) { nlist.Add(rtn); } minRequiredStrokes += nlist_rels.Count; applyRules(nlist); //} if (nlist.Count > 0 && nlist[0] == ParseTreeNode.EndOfBaseline) { nlist.RemoveAt(0); // ! } // remove any leftover relation nodes n.children.Remove(nc); List <ParseTreeNode> n_children_tmp = new List <ParseTreeNode>(n.children); for (int i = 0; i < n_children_tmp.Count; i++) { if (n_children_tmp[i] is RelationTreeNode) { n.children.Remove(n_children_tmp[i]); } } foreach (RelationTreeNode rtn in nlist_rels) { nlist.Remove(rtn); } popCurrentState(); } } } else { // NONTERMINALS //n.lexResult.segment.classification[0].symbol; List <string[]> productions = grammar.GetProductions(n.nodeType); if (productions == null) { #if DEBUG Console.Error.WriteLine("Error: invalid nonterminal ({0}).", n.nodeType); #endif return; } // remove one for the token we are replacing with productions minRequiredStrokes--; foreach (string[] production in productions) { minRequiredStrokes += production.Length; // prune by number of strokes left if (unusedInputStrokes < minRequiredStrokes) { minRequiredStrokes -= production.Length; continue; } // prune based on the candidate symbols and the first rule in production bool candidate_can_be_generated = false; foreach (LexerResult lr in candidateSymbols) { foreach (Classification csf in lr.segment.classification) { if (grammar.NonTerminalCanGenerateTerminal(production[0], csf.symbol)) { candidate_can_be_generated = true; break; } } if (candidate_can_be_generated) { break; } } if (!candidate_can_be_generated) { minRequiredStrokes -= production.Length; continue; } List <ParseTreeNode> nodes = new List <ParseTreeNode>(); foreach (string p in production) { ParseTreeNode n0 = new ParseTreeNode(); n0.nodeType = p; n0.lexResult = null; nodes.Add(n0); n.children.Add(n0); } for (int i = nodes.Count - 1; i >= 0; i--) { nlist.Insert(0, nodes[i]); } applyRules(nlist); // restore min required strokes minRequiredStrokes -= production.Length; foreach (ParseTreeNode node in nodes) { n.children.Remove(node); nlist.Remove(node); } } minRequiredStrokes++; } }