docs: def parse_attribute(tokens, is_merc):
      """ Parse a token stream from inside an attribute selector.
      
          Enter this function after a left-bracket is found:
          http://www.w3.org/TR/CSS2/selector.html#attribute-selectors
      """
      #
      # Local helper functions
      #
  
      def next_scalar(tokens, op):
          """ Look for a scalar value just after an attribute selector operator.
          """
          while True:
              tname, tvalue, line, col = tokens.next()
              if tname == 'NUMBER':
                  try:
                      value = int(tvalue)
                  except ValueError:
                      value = float(tvalue)
                  return value
              elif (tname, tvalue) == ('CHAR', '-'):
                  tname, tvalue, line, col = tokens.next()
                  if tname == 'NUMBER':
                      try:
                          value = int(tvalue)
                      except ValueError:
                          value = float(tvalue)
                      return -value
                  else:
                      raise ParseException('Unexpected non-number after a minus sign', line, col)
              elif tname in ('STRING', 'IDENT'):
                  if op in ('<', '<=', '=>', '>'):
                      raise ParseException('Selector attribute must use a number for comparison tests', line, col)
                  if tname == 'STRING':
                      return tvalue[1:-1]
                  else:
                      return tvalue
              elif tname != 'S':
                  raise ParseException('Unexpected non-scalar token in attribute', line, col)
      
      def finish_attribute(tokens):
          """ Look for the end of an attribute selector operator.
          """
          while True:
              tname, tvalue, line, col = tokens.next()
              if (tname, tvalue) == ('CHAR', ']'):
                  return
              elif tname != 'S':
                  raise ParseException('Found something other than a closing right-bracket at the end of attribute', line, col)
      
      #
      # The work.
      #
      
      while True:
          tname, tvalue, line, col = tokens.next()
          
          if tname == 'IDENT':
              property = tvalue
              
              while True:
                  tname, tvalue, line, col = tokens.next()
                  
                  if (tname, tvalue) in [('CHAR', '<'), ('CHAR', '>')]:
                      _tname, _tvalue, line, col = tokens.next()
          
                      if (_tname, _tvalue) == ('CHAR', '='):
                          #
                          # Operator is one of '<=', '>='
                          #
                          op = tvalue + _tvalue
                          value = next_scalar(tokens, op)
                          finish_attribute(tokens)
                          return SelectorAttributeTest(property, op, value)
                      
                      else:
                          #
                          # Operator is one of '<', '>' and we popped a token too early
                          #
                          op = tvalue
                          value = next_scalar(chain([(_tname, _tvalue, line, col)], tokens), op)
                          finish_attribute(tokens)
                          return SelectorAttributeTest(property, op, value)
                  
                  elif (tname, tvalue) == ('CHAR', '!'):
                      _tname, _tvalue, line, col = tokens.next()
          
                      if (_tname, _tvalue) == ('CHAR', '='):
                          #
                          # Operator is '!='
                          #
                          op = tvalue + _tvalue
                          value = next_scalar(tokens, op)
                          finish_attribute(tokens)
                          return SelectorAttributeTest(property, op, value)
                      
                      else:
                          raise ParseException('Malformed operator in attribute selector', line, col)
                  
                  elif (tname, tvalue) == ('CHAR', '='):
                      #
                      # Operator is '='
                      #
                      op = tvalue
                      value = next_scalar(tokens, op)
                      finish_attribute(tokens)
                      return SelectorAttributeTest(property, op, value)
                  
                  elif tname != 'S':
                      raise ParseException('Missing operator in attribute selector', line, col)
          
          elif tname != 'S':
              raise ParseException('Unexpected token in attribute selector', line, col)
  
      raise ParseException('Malformed attribute selector', line, col)