def _compile_impossible(self, element, *args, **kwargs): # Override this to avoid VoidRefs disabling entire rules/grammars. # Use a special <_impossible> private rule instead. Only add the # special rule if it isn't in the result grammar. grammar = args[0] if "_impossible" not in grammar.rule_names: # Check that the impossible literal contains only valid words. words = set(self.impossible_literal.split()) valid_literal = bool(words) for word in words: if not valid_literal: break if not self.engine.check_valid_word(word): valid_literal = False if valid_literal: expansion = jsgf.Literal(self.impossible_literal) else: # Fallback on a NullRef. There are some problems with using # these, but they get the job done for simple rules. expansion = jsgf.NullRef() grammar.add_rule( jsgf.Rule(name="_impossible", visible=False, expansion=expansion)) return jsgf.NamedRuleRef("_impossible")
def _compile_literal(self, element, *args, **kwargs): # Build literals as sequences and use <NULL> for unknown words. children = [] for word in element.words: if self.engine.check_valid_word(word): children.append(jsgf.Literal(word)) else: children.append( self.compile_element(elements_.Impossible(), *args, **kwargs)) # Save the unknown word. args[1].add(word) return jsgf.Sequence(*children)
def get_jsgf_equiv(self, state): """ Take a TranslationState object containing a dragonfly element return the same object with the 'expansion' member set to the equivalent JSGF expansion object. :type state: TranslationState :return TranslationState """ element = state.element def get_equiv_children(): children = [] for child in state.element.children: state.element = child self.get_jsgf_equiv(state) children.append(state.expansion) return children if isinstance(element, Literal): # Literal == word list text = " ".join(element.words) state.expansion = jsgf.Literal(text) elif isinstance(element, (RuleRef, Rule)): # Translate the dragonfly rule reference self.translate_rule_ref(state) # DictListRef should be checked before ListRef because it is a subclass elif isinstance(element, (DictListRef, DictList)): self.translate_dict_list_ref(state) elif isinstance(element, (ListRef, List)): self.translate_list_ref(state) elif isinstance(element, Dictation): # A Sphinx decoder for handling dictation will be prepared and used # when necessary. state.expansion = jsgf.ext.Dictation() elif isinstance(element, Impossible): # VoidRef is the equivalent of dragonfly's Impossible element. # It is also automatically used by pyjsgf if an expansion that should # have at least one child (e.g. Sequence/Repeat) doesn't have any at # compile time. state.expansion = VoidRef() elif element.children == (): # improbable ElementBase case state.expansion = jsgf.Expansion([]) # Repetition should be checked before Sequence because it is a subclass elif isinstance(element, Repetition): # Repetition should have at least one child assert len(state.element.children) > 0 if self._has_dictation_descendant(element): self.translate_repetition_with_dictation(state) else: # Translate the first child only. The second child is of the form: # [first_child [first_child ... first_child ] ... ] # This is how matching a limited number of repetitions is done. # Limitation (min/max) values for Repetition elements are ignored # for the Sphinx engine for the moment. equiv_child = get_equiv_children()[0] state.expansion = PatchedRepeat(equiv_child) elif isinstance(element, Sequence): state.expansion = jsgf.Sequence(*get_equiv_children()) elif isinstance(element, Alternative): if len(state.element.children) == 1: # Skip redundant (1 child) alternatives state.element = state.element.children[0] self.get_jsgf_equiv(state) else: state.expansion = jsgf.AlternativeSet(*get_equiv_children()) elif isinstance(element, Optional): equiv_children = get_equiv_children() if len(equiv_children) != 1: raise TranslationError("Optional grouping may only have 1 child.") state.expansion = jsgf.OptionalGrouping(equiv_children[0]) return state
def _compile_literal(self, element, *args, **kwargs): return jsgf.Literal(" ".join(element.words))
def get_jsgf_equiv(self, state): """ Take a TranslationState object containing a dragonfly element return the same object with the 'expansion' member set to the equivalent JSGF expansion object. :type state: TranslationState :return TranslationState """ element = state.element def get_equiv_children(): children = [] for child in state.element.children: state.element = child self.get_jsgf_equiv(state) children.append(state.expansion) return children if isinstance(element, Literal): # Literal == word list state.expansion = jsgf.Literal(element.gstring()) elif isinstance(element, (RuleRef, Rule)): # Translate the dragonfly rule reference self.translate_rule_ref(state) # DictListRef should be checked before ListRef because it is a subclass elif isinstance(element, (DictListRef, DictList)): self.translate_dict_list_ref(state) elif isinstance(element, (ListRef, List)): self.translate_list_ref(state) elif isinstance(element, Dictation): # A Sphinx decoder for handling dictation will be prepared and used # when necessary. state.expansion = jsgf.ext.Dictation() elif isinstance(element, Impossible): state.expansion = JSGFImpossible() elif element.children == (): # improbable ElementBase case state.expansion = jsgf.Expansion([]) # Repetition should be checked before Sequence because it is a subclass elif isinstance(element, Repetition): # Repetition should have at least one child assert len(state.element.children) > 0 if self._has_dictation_descendant(element): self.translate_repetition_with_dictation(state) elif len(element.children) == 1: state.expansion = jsgf.Repeat(*get_equiv_children()) else: state.expansion = jsgf.Sequence(*get_equiv_children()) elif isinstance(element, Sequence): state.expansion = jsgf.Sequence(*get_equiv_children()) elif isinstance(element, Alternative): if len(state.element.children) == 1: # Skip redundant (1 child) alternatives state.element = state.element.children[0] self.get_jsgf_equiv(state) else: state.expansion = jsgf.AlternativeSet(*get_equiv_children()) elif isinstance(element, Optional): equiv_children = get_equiv_children() if len(equiv_children) != 1: raise TranslationError( "Optional grouping may only have 1 child.") state.expansion = jsgf.OptionalGrouping(equiv_children[0]) return state