nodes: 0, module; 1, function_definition; 2, function_name:sort_trigger_set; 3, parameters; 4, block; 5, identifier:triggers; 6, default_parameter; 7, default_parameter; 8, expression_statement; 9, if_statement; 10, comment:# KEEP IN MIND: the `triggers` array is composed of array elements of the form; 11, comment:# ["trigger text", pointer to trigger data]; 12, comment:# So this code will use e.g. `trig[0]` when referring to the trigger text.; 13, comment:# Create a list of trigger objects map.; 14, expression_statement; 15, for_statement; 16, comment:# Priority order of sorting criteria:; 17, comment:# weight, inherit, is_empty, star, pound, under, option, wordcount, len, alphabet; 18, expression_statement; 19, return_statement; 20, identifier:exclude_previous; 21, True; 22, identifier:say; 23, None; 24, comment:"""Sort a group of triggers in optimal sorting order.
  
      The optimal sorting order is, briefly:
      * Atomic triggers (containing nothing but plain words and alternation
        groups) are on top, with triggers containing the most words coming
        first. Triggers with equal word counts are sorted by length, and then
        alphabetically if they have the same length.
      * Triggers containing optionals are sorted next, by word count like
        atomic triggers.
      * Triggers containing wildcards are next, with ``_`` (alphabetic)
        wildcards on top, then ``#`` (numeric) and finally ``*``.
      * At the bottom of the sorted list are triggers consisting of only a
        single wildcard, in the order: ``_``, ``#``, ``*``.
  
      Triggers that have ``{weight}`` tags are grouped together by weight
      value and sorted amongst themselves. Higher weighted groups are then
      ordered before lower weighted groups regardless of the normal sorting
      algorithm.
  
      Triggers that come from topics which inherit other topics are also
      sorted with higher priority than triggers from the inherited topics.
  
      Arguments:
          triggers ([]str): Array of triggers to sort.
          exclude_previous (bool): Create a sort buffer for 'previous' triggers.
          say (function): A reference to ``RiveScript._say()`` or provide your
              own function.
      """; 25, comparison_operator:say is None; 26, block; 27, assignment; 28, pattern_list; 29, call; 30, block; 31, assignment; 32, list_comprehension; 33, identifier:say; 34, None; 35, expression_statement; 36, identifier:trigger_object_list; 37, list; 38, identifier:index; 39, identifier:trig; 40, identifier:enumerate; 41, argument_list; 42, if_statement; 43, expression_statement; 44, comment:# Extract only the text of the trigger, with possible tag of inherit; 45, comment:# See if it has a weight tag; 46, expression_statement; 47, if_statement; 48, comment:# See if it has an inherits tag.; 49, expression_statement; 50, if_statement; 51, expression_statement; 52, identifier:sorted_list; 53, call; 54, subscript; 55, for_in_clause; 56, assignment; 57, identifier:triggers; 58, boolean_operator; 59, block; 60, assignment; 61, assignment; 62, identifier:match; 63, comment:# Value of math is not None if there is a match.; 64, block; 65, assignment; 66, identifier:match; 67, block; 68, else_clause; 69, call; 70, identifier:sorted; 71, argument_list; 72, identifier:triggers; 73, attribute; 74, identifier:item; 75, identifier:sorted_list; 76, identifier:say; 77, lambda; 78, identifier:exclude_previous; 79, subscript; 80, continue_statement; 81, identifier:pattern; 82, subscript; 83, pattern_list; 84, expression_list; 85, expression_statement; 86, comment:# Get the weight from the tag ``{weight}``; 87, identifier:match; 88, call; 89, expression_statement; 90, comment:# Get inherit value from the tag ``{inherit}``; 91, expression_statement; 92, expression_statement; 93, comment:# Remove the inherit tag if any; 94, block; 95, attribute; 96, argument_list; 97, identifier:trigger_object_list; 98, keyword_argument; 99, identifier:item; 100, identifier:index; 101, lambda_parameters; 102, identifier:x; 103, subscript; 104, string:"previous"; 105, identifier:trig; 106, integer:0; 107, identifier:match; 108, identifier:weight; 109, call; 110, integer:0; 111, assignment; 112, attribute; 113, argument_list; 114, assignment; 115, call; 116, assignment; 117, expression_statement; 118, comment:# If not found any inherit, set it to the maximum value, to place it last in the sort; 119, identifier:trigger_object_list; 120, identifier:append; 121, call; 122, identifier:key; 123, call; 124, identifier:x; 125, identifier:trig; 126, integer:1; 127, attribute; 128, argument_list; 129, identifier:weight; 130, call; 131, identifier:re; 132, identifier:search; 133, attribute; 134, identifier:pattern; 135, identifier:inherit; 136, call; 137, identifier:say; 138, argument_list; 139, subscript; 140, assignment; 141, assignment; 142, identifier:TriggerObj; 143, argument_list; 144, identifier:attrgetter; 145, argument_list; 146, identifier:re; 147, identifier:search; 148, attribute; 149, subscript; 150, identifier:int; 151, argument_list; 152, identifier:RE; 153, identifier:inherit; 154, identifier:int; 155, argument_list; 156, binary_operator:"\t\t\tTrigger belongs to a topic which inherits other topics: level=" + str(inherit); 157, subscript; 158, integer:0; 159, identifier:pattern; 160, call; 161, identifier:inherit; 162, attribute; 163, identifier:pattern; 164, identifier:index; 165, identifier:weight; 166, identifier:inherit; 167, string; 168, string; 169, string; 170, string; 171, string; 172, string; 173, string; 174, string; 175, string; 176, string; 177, identifier:RE; 178, identifier:weight; 179, identifier:trig; 180, integer:0; 181, call; 182, call; 183, string:"\t\t\tTrigger belongs to a topic which inherits other topics: level="; 184, call; 185, identifier:triggers; 186, identifier:index; 187, attribute; 188, argument_list; 189, identifier:sys; 190, identifier:maxsize; 191, string_content:weight; 192, string_content:inherit; 193, string_content:is_empty; 194, string_content:star; 195, string_content:pound; 196, string_content:under; 197, string_content:option; 198, string_content:wordcount; 199, string_content:len; 200, string_content:alphabet; 201, attribute; 202, argument_list; 203, attribute; 204, argument_list; 205, identifier:str; 206, argument_list; 207, identifier:re; 208, identifier:sub; 209, attribute; 210, string:""; 211, identifier:pattern; 212, identifier:match; 213, identifier:group; 214, integer:1; 215, identifier:match; 216, identifier:group; 217, integer:1; 218, identifier:inherit; 219, identifier:RE; 220, identifier:inherit
code: def sort_trigger_set(triggers, exclude_previous=True, say=None):
      """Sort a group of triggers in optimal sorting order.
  
      The optimal sorting order is, briefly:
      * Atomic triggers (containing nothing but plain words and alternation
        groups) are on top, with triggers containing the most words coming
        first. Triggers with equal word counts are sorted by length, and then
        alphabetically if they have the same length.
      * Triggers containing optionals are sorted next, by word count like
        atomic triggers.
      * Triggers containing wildcards are next, with ``_`` (alphabetic)
        wildcards on top, then ``#`` (numeric) and finally ``*``.
      * At the bottom of the sorted list are triggers consisting of only a
        single wildcard, in the order: ``_``, ``#``, ``*``.
  
      Triggers that have ``{weight}`` tags are grouped together by weight
      value and sorted amongst themselves. Higher weighted groups are then
      ordered before lower weighted groups regardless of the normal sorting
      algorithm.
  
      Triggers that come from topics which inherit other topics are also
      sorted with higher priority than triggers from the inherited topics.
  
      Arguments:
          triggers ([]str): Array of triggers to sort.
          exclude_previous (bool): Create a sort buffer for 'previous' triggers.
          say (function): A reference to ``RiveScript._say()`` or provide your
              own function.
      """
      if say is None:
          say = lambda x: x
  
      # KEEP IN MIND: the `triggers` array is composed of array elements of the form
      # ["trigger text", pointer to trigger data]
      # So this code will use e.g. `trig[0]` when referring to the trigger text.
  
      # Create a list of trigger objects map.
      trigger_object_list = []
      for index, trig in enumerate(triggers):
  
          if exclude_previous and trig[1]["previous"]:
              continue
  
          pattern = trig[0]  # Extract only the text of the trigger, with possible tag of inherit
  
          # See if it has a weight tag
          match, weight = re.search(RE.weight, trig[0]), 0
          if match:  # Value of math is not None if there is a match.
              weight = int(match.group(1))  # Get the weight from the tag ``{weight}``
  
          # See if it has an inherits tag.
          match = re.search(RE.inherit, pattern)
          if match:
              inherit = int(match.group(1))  # Get inherit value from the tag ``{inherit}``
              say("\t\t\tTrigger belongs to a topic which inherits other topics: level=" + str(inherit))
              triggers[index][0] = pattern = re.sub(RE.inherit, "", pattern)  # Remove the inherit tag if any
          else:
              inherit = sys.maxsize  # If not found any inherit, set it to the maximum value, to place it last in the sort
  
          trigger_object_list.append(TriggerObj(pattern, index, weight, inherit))
  
      # Priority order of sorting criteria:
      # weight, inherit, is_empty, star, pound, under, option, wordcount, len, alphabet
      sorted_list = sorted(trigger_object_list,
                           key=attrgetter('weight', 'inherit', 'is_empty', 'star', 'pound',
                                          'under', 'option', 'wordcount', 'len', 'alphabet'))
      return [triggers[item.index] for item in sorted_list]