/** * Parses the given RuleName into a network of GrammarNodes. * * @param initialRuleName * the RuleName rule to parse * @return a grammar graph */ private GrammarGraph ProcessRuleName(JSGFRuleName initialRuleName) { this.LogInfo("parseRuleName: " + initialRuleName); GrammarGraph result = RuleStack.Contains(initialRuleName.GetRuleName()); if (result != null) { // its a recursive call return(result); } else { result = new GrammarGraph(this); RuleStack.Push(initialRuleName.GetRuleName(), result); } JSGFRuleName ruleName = _ruleGrammar.Resolve(initialRuleName); if (ruleName == JSGFRuleName.Null) { result.StartNode.Add(result.EndNode, 0.0f); } else if (ruleName == JSGFRuleName.Void) { // no connection for void } else { if (ruleName == null) { throw new JSGFGrammarException("Can't resolve " + initialRuleName + " g " + initialRuleName.GetFullGrammarName()); } JSGFRuleGrammar rg = Manager.RetrieveGrammar(ruleName .GetFullGrammarName()); if (rg == null) { throw new JSGFGrammarException("Can't resolve grammar name " + ruleName.GetFullGrammarName()); } JSGFRule rule = rg.GetRule(ruleName.GetSimpleRuleName()); if (rule == null) { throw new JSGFGrammarException("Can't resolve rule: " + ruleName.GetRuleName()); } GrammarGraph ruleResult = ProcessRule(rule); if (result != ruleResult) { result.StartNode.Add(ruleResult.StartNode, 0.0f); ruleResult.EndNode.Add(result.EndNode, 0.0f); } } RuleStack.Pop(); return(result); }
/** * Resolve a simple or qualified rule name as a full rule name. * * @param ruleName * the name of the rule. */ public JSGFRuleName Resolve(JSGFRuleName ruleName) { // System.out.println ("Resolving " + ruleName); JSGFRuleName rn = new JSGFRuleName(ruleName.GetRuleName()); String simpleName = rn.GetSimpleRuleName(); String grammarName = rn.GetSimpleGrammarName(); String packageName = rn.GetPackageName(); String fullGrammarName = rn.GetFullGrammarName(); // Check for badly formed RuleName if (packageName != null && grammarName == null) { throw new JSGFGrammarException("Error: badly formed rulename " + rn); } if (ruleName.GetSimpleRuleName().Equals("NULL")) { return(JSGFRuleName.Null); } if (ruleName.GetSimpleRuleName().Equals("VOID")) { return(JSGFRuleName.Void); } // Check simple case: a local rule reference if (fullGrammarName == null && GetRule(simpleName) != null) { return(new JSGFRuleName(_name + '.' + simpleName)); } // Check for fully-qualified reference if (fullGrammarName != null) { JSGFRuleGrammar g = _manager.RetrieveGrammar(fullGrammarName); if (g != null) { if (g.GetRule(simpleName) != null) { // we have a successful resolution return(new JSGFRuleName(fullGrammarName + '.' + simpleName)); } } } // Collect all matching imports into a list. After trying to // match rn to each import statement the vec will have // size()=0 if rn is unresolvable // size()=1 if rn is properly resolvable // size()>1 if rn is an ambiguous reference List <JSGFRuleName> matches = new List <JSGFRuleName>(); // Get list of imports // Add local grammar to simply the case of checking for // a qualified or fully-qualified local reference. List <JSGFRuleName> imports = new List <JSGFRuleName>(this.Imports); imports.Add(new JSGFRuleName(_name + ".*")); // Check each import statement for a possible match foreach (JSGFRuleName importName in imports) { // TO-DO: update for JSAPI 1.0 String importSimpleName = importName.GetSimpleRuleName(); String importGrammarName = importName.GetSimpleGrammarName(); String importFullGrammarName = importName.GetFullGrammarName(); // Check for badly formed import name if (importFullGrammarName == null) { throw new JSGFGrammarException("Error: badly formed import " + ruleName); } // Get the imported grammar JSGFRuleGrammar gref = _manager.RetrieveGrammar(importFullGrammarName); if (gref == null) { Console.WriteLine("Warning: import of unknown grammar " + ruleName + " in " + _name); continue; } // If import includes simpleName, test that it really exists if (!importSimpleName.Equals("*") && gref.GetRule(importSimpleName) == null) { Console.WriteLine("Warning: import of undefined rule " + ruleName + " in " + _name); continue; } // Check for fully-qualified or qualified reference if (importFullGrammarName.Equals(fullGrammarName) || importGrammarName.Equals(fullGrammarName)) { // Know that either // import <ipkg.igram.???> matches <pkg.gram.???> // OR // import <ipkg.igram.???> matches <gram.???> // (ipkg may be null) if (importSimpleName.Equals("*")) { if (gref.GetRule(simpleName) != null) { // import <pkg.gram.*> matches <pkg.gram.rulename> matches.Add(new JSGFRuleName(importFullGrammarName + '.' + simpleName)); } continue; } else { // Now testing // import <ipkg.igram.iRuleName> against <??.gram.ruleName> // if (importSimpleName.Equals(simpleName)) { // import <pkg.gram.rulename> exact match for // <???.gram.rulename> matches.Add(new JSGFRuleName(importFullGrammarName + '.' + simpleName)); } continue; } } // If we get here and rulename is qualified or fully-qualified // then the match failed - try the next import statement if (fullGrammarName != null) { continue; } // Now test // import <ipkg.igram.*> against <simpleName> if (importSimpleName.Equals("*")) { if (gref.GetRule(simpleName) != null) { // import <pkg.gram.*> matches <simpleName> matches.Add(new JSGFRuleName(importFullGrammarName + '.' + simpleName)); } continue; } // Finally test // import <ipkg.igram.iSimpleName> against <simpleName> if (importSimpleName.Equals(simpleName)) { matches.Add(new JSGFRuleName(importFullGrammarName + '.' + simpleName)); continue; } } // The return behavior depends upon number of matches switch (matches.Count) { case 0: // Return null if rulename is unresolvable return(null); case 1: // Return successfully return(matches[0]); default: // Throw exception if ambiguous reference StringBuilder b = new StringBuilder(); b.Append("Warning: ambiguous reference ").Append(rn).Append(" in ").Append(_name).Append(" to "); foreach (JSGFRuleName tmp in matches) { b.Append(tmp).Append(" and "); } b.Length = (b.Length - 5); throw new JSGFGrammarException(b.ToString()); } }