Пример #1
0
    def _compile_rule_chunk(self, chunk_id):
        # Loop through all known rule names, and if they are defined within
        #  this grammar create a rule definition entry.
        definitions = []
        for name, id in zip(self._rules,
                            xrange(1, len(self._rules) + 1)):

            # Skip imported rules.
            if name in self._import_rules:
                if name in self._rule_definitions:
                    raise CompilerError("Rule '%s' cannot be both imported" \
                                        " and defined in a grammar" % name)
                continue

            # Make sure that a definition has been given.
            if name not in self._rule_definitions:
                raise CompilerError("Rule '%s' is neither imported" \
                                    " nor defined" % name)
    
            # Build the definition sequence for this rule.  
            elements = []
            for t, v in self._rule_definitions[name]:
                # Definition element:
                #  - wType; start:1, end:2, word:3, rule:4, list:6
                #  - wProb; probability rating, use 0.
                #  - dwValue; depends on wType as follows:
                #     - if wType is start or end, then dwValue is one of
                #        sequence:1, alternative:2, repetition:3, optional:4
                #     - if wType is word, rule, or list, then dwValue is
                #        the ID of the corresponding element.
                element = struct.pack("HHL", t, 0, v)
                elements.append(element)

            # Definition header:
            #  - dwSize; size of this rule definition in bytes including
            #     this header.
            #  - dwNum; the ID of this rule.
            definition_size = 8 + sum([len(s) for s in elements])
            definition = struct.pack("LL", definition_size, id)
            definition += "".join(elements)

            definitions.append(definition)

        # Concatenate all the rule definitions.
        definition_data = "".join(definitions)

        # Rule definition chunk header:
        #  - dwChunkId; rule definitions:3
        #  - dwChunkSize; size of this chunk in bytes excluding this header.
        header = struct.pack("LL", chunk_id, len(definition_data))

        # Return the header and the rule definitions.
        return header + definition_data
Пример #2
0
 def end_optional(self):
     """End a optional structure in the rule currently being defined."""
     # Make sure a rule is being defined at the moment.
     if not self._current_rule_name:
         raise CompilerError("Cannot end a optional because" \
                            " no rule is currently being defined.")
     # Append the end-tag.
     self._current_rule_definition.append(
         (self._end_type, self._opt_value) )
Пример #3
0
 def start_repetition(self):
     """start a repetition structure in the rule currently being defined."""
     # Make sure a rule is being defined at the moment.
     if not self._current_rule_name:
         raise CompilerError("Cannot start a repetition because" \
                            " no rule is currently being defined.")
     # Append the start-tag.
     self._current_rule_definition.append(
         (self._start_type, self._rep_value) )
Пример #4
0
    def start_rule_definition(self, name, exported=False):
        """start defining a rule."""

        # Make sure no rule is being defined at the moment.
        if self._current_rule_name:
            raise CompilerError("Cannot start defining a rule while" \
                               "a different rule is already being defined.")

        assert isinstance(name, str), "The rule name must be a string."
        self._current_rule_name = name
        self._current_rule_export = exported
        self._current_rule_definition = []
Пример #5
0
    def _compile_rule_ref(self, element, src_state, dst_state, grammar,
                          grammar_handle):
        rule_handle = grammar_handle.Rules.FindRule(element.rule.name)
        if not rule_handle:
            grammar.add_rule(element.rule)
            self._compile_rule(element.rule, grammar, grammar_handle)
            rule_handle = grammar_handle.Rules.FindRule(element.rule.name)
            if not rule_handle:
                raise CompilerError(
                    "%s: Failed to create rule dependency: %r." %
                    (self, element.rule.name))

        src_state.AddRuleTransition(dst_state, rule_handle)
Пример #6
0
 def add_rule(self, rule, imported = False):
     """Append a rule reference to the rule currently being defined."""
     # Make sure a rule is being defined at the moment.
     if not self._current_rule_name:
         raise CompilerError("Cannot add rule '%s' because" \
                            " no rule is currently being defined." % rule)
     # Determine this rule's ID.  If this rule has not been used before,
     # register it.
     if rule not in self._rules:
         self._rules.append(rule)
         if imported: self._import_rules.append(rule)
         id = len(self._rules)
     # If this rule has been referenced multiple times, make sure that
     # it has either always being imported or never been imported.
     elif imported != (rule in self._import_rules):
         raise CompilerError("Rule '%s' cannot be referenced as both" \
                            " imported and not imported within a" \
                            " grammar." % rule)
     else:
         id = self._rules.index(rule) + 1
     # Append the rule to the rule currently being defined.
     self._current_rule_definition.append( (self._rule_type, id) )
Пример #7
0
 def add_list(self, list):
     """Append a list to the rule currently being defined."""
     # Make sure a rule is being defined at the moment.
     if not self._current_rule_name:
         raise CompilerError("Cannot add list '%s' because" \
                            " no rule is currently being defined." % list)
     # Determine this list's ID.  If this list has not been used before,
     # register it.
     if list not in self._lists:
         self._lists.append(list)
         id = len(self._lists)
     else:
         id = self._lists.index(list) + 1
     # Append the list to the rule currently being defined.
     self._current_rule_definition.append( (self._list_type, id) )
Пример #8
0
 def add_word(self, word):
     """Append a literal word to the rule currently being defined."""
     # Make sure a rule is being defined at the moment.
     if not self._current_rule_name:
         raise CompilerError("Cannot add word '%s' because" \
                            " no rule is currently being defined." % word)
     # Determine this word's ID.  If this word has not been used before,
     # register it.
     if word not in self._words:
         self._words.append(word)
         id = len(self._words)
     else:
         id = self._words.index(word) + 1
     # Append the word to the rule currently being defined.
     self._current_rule_definition.append( (self._word_type, id) )
Пример #9
0
    def end_rule_definition(self):
        """End defining a rule."""

        # Make sure a rule is being defined at the moment.
        if not self._current_rule_name:
            raise CompilerError("Cannot end defining a rule when" \
                               " no rule is being defined.")

        # Make sure that no other rule has been defined with this name.
        if self._current_rule_name in self._rule_definitions:
            raise CompilerError("Rule '%s' defined more than once." % \
                                self._current_rule_name)

        # If this rule has not been used before, register it.
        if self._current_rule_name not in self._rules:
            self._rules.append(self._current_rule_name)
        if self._current_rule_export:
            self._export_rules.append(self._current_rule_name)
        self._rule_definitions[self._current_rule_name] = \
            self._current_rule_definition

        self._current_rule_name = None
        self._current_rule_export = None
        self._current_rule_definition = None
Пример #10
0
    def compile(self):
        """Compile a binary grammar of this compiler's current state."""

        # Make sure no rule is being defined at the moment.
        if self._current_rule_name:
            raise CompilerError("Cannot compile grammar while a rule" \
                               " is being defined.")

        # Grammar header:
        #   - dwType; use 0.
        #   - dwFlags; use 0.
        output = [struct.pack("LL", 0, 0)]

        # Lists of the names and IDs of exports, imports, lists, and words.
        output.append(self._compile_id_chunk(4, self._export_rules, self._rules))
        output.append(self._compile_id_chunk(5, self._import_rules, self._rules))
        output.append(self._compile_id_chunk(6, self._lists, self._lists))
        output.append(self._compile_id_chunk(2, self._words, self._words))

        # List of rule definitions.
        output.append(self._compile_rule_chunk(3))

        # Return a concatenation of the header and chunks.
        return "".join(output)