Exemplo n.º 1
0
    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")
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
 def _compile_literal(self, element, *args, **kwargs):
     return jsgf.Literal(" ".join(element.words))
Exemplo n.º 5
0
    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