home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1990 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  29.0 KB  |  930 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import re
  5. from lxml import etree
  6. __all__ = [
  7.     'SelectorSyntaxError',
  8.     'ExpressionError',
  9.     'CSSSelector']
  10.  
  11. try:
  12.     _basestring = basestring
  13. except NameError:
  14.     _basestring = str
  15.  
  16.  
  17. class SelectorSyntaxError(SyntaxError):
  18.     pass
  19.  
  20.  
  21. class ExpressionError(RuntimeError):
  22.     pass
  23.  
  24.  
  25. class CSSSelector(etree.XPath):
  26.     
  27.     def __init__(self, css):
  28.         path = css_to_xpath(css)
  29.         etree.XPath.__init__(self, path)
  30.         self.css = css
  31.  
  32.     
  33.     def __repr__(self):
  34.         return '<%s %s for %r>' % (self.__class__.__name__, hex(abs(id(self)))[2:], self.css)
  35.  
  36.  
  37.  
  38. try:
  39.     _unicode = unicode
  40.     _unichr = unichr
  41. except NameError:
  42.     _unicode = str
  43.     _unichr = chr
  44.  
  45.  
  46. class _UniToken(_unicode):
  47.     
  48.     def __new__(cls, contents, pos):
  49.         obj = _unicode.__new__(cls, contents)
  50.         obj.pos = pos
  51.         return obj
  52.  
  53.     
  54.     def __repr__(self):
  55.         return '%s(%s, %r)' % (self.__class__.__name__, _unicode.__repr__(self), self.pos)
  56.  
  57.  
  58.  
  59. class Symbol(_UniToken):
  60.     pass
  61.  
  62.  
  63. class String(_UniToken):
  64.     pass
  65.  
  66.  
  67. class Token(_UniToken):
  68.     pass
  69.  
  70.  
  71. class Class(object):
  72.     
  73.     def __init__(self, selector, class_name):
  74.         self.selector = selector
  75.         self.class_name = class_name
  76.  
  77.     
  78.     def __repr__(self):
  79.         return '%s[%r.%s]' % (self.__class__.__name__, self.selector, self.class_name)
  80.  
  81.     
  82.     def xpath(self):
  83.         sel_xpath = self.selector.xpath()
  84.         sel_xpath.add_condition("contains(concat(' ', normalize-space(@class), ' '), %s)" % xpath_literal(' ' + self.class_name + ' '))
  85.         return sel_xpath
  86.  
  87.  
  88.  
  89. class Function(object):
  90.     unsupported = [
  91.         'target',
  92.         'lang',
  93.         'enabled',
  94.         'disabled']
  95.     
  96.     def __init__(self, selector, type, name, expr):
  97.         self.selector = selector
  98.         self.type = type
  99.         self.name = name
  100.         self.expr = expr
  101.  
  102.     
  103.     def __repr__(self):
  104.         return '%s[%r%s%s(%r)]' % (self.__class__.__name__, self.selector, self.type, self.name, self.expr)
  105.  
  106.     
  107.     def xpath(self):
  108.         sel_path = self.selector.xpath()
  109.         if self.name in self.unsupported:
  110.             raise ExpressionError('The psuedo-class %r is not supported' % self.name)
  111.         self.name in self.unsupported
  112.         method = '_xpath_' + self.name.replace('-', '_')
  113.         if not hasattr(self, method):
  114.             raise ExpressionError('The psuedo-class %r is unknown' % self.name)
  115.         hasattr(self, method)
  116.         method = getattr(self, method)
  117.         return method(sel_path, self.expr)
  118.  
  119.     
  120.     def _xpath_nth_child(self, xpath, expr, last = False, add_name_test = True):
  121.         (a, b) = parse_series(expr)
  122.         if not a and not b and not last:
  123.             xpath.add_condition('false() and position() = 0')
  124.             return xpath
  125.         if add_name_test:
  126.             xpath.add_name_test()
  127.         
  128.         xpath.add_star_prefix()
  129.         if a == 0:
  130.             if last:
  131.                 b = 'last() - %s' % b
  132.             
  133.             xpath.add_condition('position() = %s' % b)
  134.             return xpath
  135.         if last:
  136.             a = -a
  137.             b = -b
  138.         
  139.         if b > 0:
  140.             b_neg = str(-b)
  141.         else:
  142.             b_neg = '+%s' % -b
  143.         if a != 1:
  144.             expr = [
  145.                 '(position() %s) mod %s = 0' % (b_neg, a)]
  146.         else:
  147.             expr = []
  148.         if b >= 0:
  149.             expr.append('position() >= %s' % b)
  150.         elif b < 0 and last:
  151.             expr.append('position() < (last() %s)' % b)
  152.         
  153.         expr = ' and '.join(expr)
  154.         if expr:
  155.             xpath.add_condition(expr)
  156.         
  157.         return xpath
  158.  
  159.     
  160.     def _xpath_nth_last_child(self, xpath, expr):
  161.         return self._xpath_nth_child(xpath, expr, last = True)
  162.  
  163.     
  164.     def _xpath_nth_of_type(self, xpath, expr):
  165.         if xpath.element == '*':
  166.             raise NotImplementedError('*:nth-of-type() is not implemented')
  167.         xpath.element == '*'
  168.         return self._xpath_nth_child(xpath, expr, add_name_test = False)
  169.  
  170.     
  171.     def _xpath_nth_last_of_type(self, xpath, expr):
  172.         return self._xpath_nth_child(xpath, expr, last = True, add_name_test = False)
  173.  
  174.     
  175.     def _xpath_contains(self, xpath, expr):
  176.         if isinstance(expr, Element):
  177.             expr = expr._format_element()
  178.         
  179.         xpath.add_condition('contains(css:lower-case(string(.)), %s)' % xpath_literal(expr.lower()))
  180.         return xpath
  181.  
  182.     
  183.     def _xpath_not(self, xpath, expr):
  184.         expr = expr.xpath()
  185.         cond = expr.condition
  186.         xpath.add_condition('not(%s)' % cond)
  187.         return xpath
  188.  
  189.  
  190.  
  191. def _make_lower_case(context, s):
  192.     return s.lower()
  193.  
  194. ns = etree.FunctionNamespace('http://codespeak.net/lxml/css/')
  195. ns.prefix = 'css'
  196. ns['lower-case'] = _make_lower_case
  197.  
  198. class Pseudo(object):
  199.     unsupported = [
  200.         'indeterminate',
  201.         'first-line',
  202.         'first-letter',
  203.         'selection',
  204.         'before',
  205.         'after',
  206.         'link',
  207.         'visited',
  208.         'active',
  209.         'focus',
  210.         'hover']
  211.     
  212.     def __init__(self, element, type, ident):
  213.         self.element = element
  214.         self.type = type
  215.         self.ident = ident
  216.  
  217.     
  218.     def __repr__(self):
  219.         return '%s[%r%s%s]' % (self.__class__.__name__, self.element, self.type, self.ident)
  220.  
  221.     
  222.     def xpath(self):
  223.         el_xpath = self.element.xpath()
  224.         if self.ident in self.unsupported:
  225.             raise ExpressionError('The psuedo-class %r is unsupported' % self.ident)
  226.         self.ident in self.unsupported
  227.         method = '_xpath_' + self.ident.replace('-', '_')
  228.         if not hasattr(self, method):
  229.             raise ExpressionError('The psuedo-class %r is unknown' % self.ident)
  230.         hasattr(self, method)
  231.         method = getattr(self, method)
  232.         el_xpath = method(el_xpath)
  233.         return el_xpath
  234.  
  235.     
  236.     def _xpath_checked(self, xpath):
  237.         xpath.add_condition("(@selected or @checked) and (name(.) = 'input' or name(.) = 'option')")
  238.         return xpath
  239.  
  240.     
  241.     def _xpath_root(self, xpath):
  242.         raise NotImplementedError
  243.  
  244.     
  245.     def _xpath_first_child(self, xpath):
  246.         xpath.add_star_prefix()
  247.         xpath.add_name_test()
  248.         xpath.add_condition('position() = 1')
  249.         return xpath
  250.  
  251.     
  252.     def _xpath_last_child(self, xpath):
  253.         xpath.add_star_prefix()
  254.         xpath.add_name_test()
  255.         xpath.add_condition('position() = last()')
  256.         return xpath
  257.  
  258.     
  259.     def _xpath_first_of_type(self, xpath):
  260.         if xpath.element == '*':
  261.             raise NotImplementedError('*:first-of-type is not implemented')
  262.         xpath.element == '*'
  263.         xpath.add_star_prefix()
  264.         xpath.add_condition('position() = 1')
  265.         return xpath
  266.  
  267.     
  268.     def _xpath_last_of_type(self, xpath):
  269.         if xpath.element == '*':
  270.             raise NotImplementedError('*:last-of-type is not implemented')
  271.         xpath.element == '*'
  272.         xpath.add_star_prefix()
  273.         xpath.add_condition('position() = last()')
  274.         return xpath
  275.  
  276.     
  277.     def _xpath_only_child(self, xpath):
  278.         xpath.add_name_test()
  279.         xpath.add_star_prefix()
  280.         xpath.add_condition('last() = 1')
  281.         return xpath
  282.  
  283.     
  284.     def _xpath_only_of_type(self, xpath):
  285.         if xpath.element == '*':
  286.             raise NotImplementedError('*:only-of-type is not implemented')
  287.         xpath.element == '*'
  288.         xpath.add_condition('last() = 1')
  289.         return xpath
  290.  
  291.     
  292.     def _xpath_empty(self, xpath):
  293.         xpath.add_condition('not(*) and not(normalize-space())')
  294.         return xpath
  295.  
  296.  
  297.  
  298. class Attrib(object):
  299.     
  300.     def __init__(self, selector, namespace, attrib, operator, value):
  301.         self.selector = selector
  302.         self.namespace = namespace
  303.         self.attrib = attrib
  304.         self.operator = operator
  305.         self.value = value
  306.  
  307.     
  308.     def __repr__(self):
  309.         if self.operator == 'exists':
  310.             return '%s[%r[%s]]' % (self.__class__.__name__, self.selector, self._format_attrib())
  311.         return '%s[%r[%s %s %r]]' % (self.__class__.__name__, self.selector, self._format_attrib(), self.operator, self.value)
  312.  
  313.     
  314.     def _format_attrib(self):
  315.         if self.namespace == '*':
  316.             return self.attrib
  317.         return '%s|%s' % (self.namespace, self.attrib)
  318.  
  319.     
  320.     def _xpath_attrib(self):
  321.         if self.namespace == '*':
  322.             return '@' + self.attrib
  323.         return '@%s:%s' % (self.namespace, self.attrib)
  324.  
  325.     
  326.     def xpath(self):
  327.         path = self.selector.xpath()
  328.         attrib = self._xpath_attrib()
  329.         value = self.value
  330.         if self.operator == 'exists':
  331.             path.add_condition(attrib)
  332.         elif self.operator == '=':
  333.             path.add_condition('%s = %s' % (attrib, xpath_literal(value)))
  334.         elif self.operator == '!=':
  335.             if value:
  336.                 path.add_condition('not(%s) or %s != %s' % (attrib, attrib, xpath_literal(value)))
  337.             else:
  338.                 path.add_condition('%s != %s' % (attrib, xpath_literal(value)))
  339.         elif self.operator == '~=':
  340.             path.add_condition("contains(concat(' ', normalize-space(%s), ' '), %s)" % (attrib, xpath_literal(' ' + value + ' ')))
  341.         elif self.operator == '|=':
  342.             path.add_condition('%s = %s or starts-with(%s, %s)' % (attrib, xpath_literal(value), attrib, xpath_literal(value + '-')))
  343.         elif self.operator == '^=':
  344.             path.add_condition('starts-with(%s, %s)' % (attrib, xpath_literal(value)))
  345.         elif self.operator == '$=':
  346.             path.add_condition('substring(%s, string-length(%s)-%s) = %s' % (attrib, attrib, len(value) - 1, xpath_literal(value)))
  347.         elif self.operator == '*=':
  348.             path.add_condition('contains(%s, %s)' % (attrib, xpath_literal(value)))
  349.         
  350.         return path
  351.  
  352.  
  353.  
  354. class Element(object):
  355.     
  356.     def __init__(self, namespace, element):
  357.         self.namespace = namespace
  358.         self.element = element
  359.  
  360.     
  361.     def __repr__(self):
  362.         return '%s[%s]' % (self.__class__.__name__, self._format_element())
  363.  
  364.     
  365.     def _format_element(self):
  366.         if self.namespace == '*':
  367.             return self.element
  368.         return '%s|%s' % (self.namespace, self.element)
  369.  
  370.     
  371.     def xpath(self):
  372.         if self.namespace == '*':
  373.             el = self.element.lower()
  374.         else:
  375.             el = '%s:%s' % (self.namespace, self.element)
  376.         return XPathExpr(element = el)
  377.  
  378.  
  379.  
  380. class Hash(object):
  381.     
  382.     def __init__(self, selector, id):
  383.         self.selector = selector
  384.         self.id = id
  385.  
  386.     
  387.     def __repr__(self):
  388.         return '%s[%r#%s]' % (self.__class__.__name__, self.selector, self.id)
  389.  
  390.     
  391.     def xpath(self):
  392.         path = self.selector.xpath()
  393.         path.add_condition('@id = %s' % xpath_literal(self.id))
  394.         return path
  395.  
  396.  
  397.  
  398. class Or(object):
  399.     
  400.     def __init__(self, items):
  401.         self.items = items
  402.  
  403.     
  404.     def __repr__(self):
  405.         return '%s(%r)' % (self.__class__.__name__, self.items)
  406.  
  407.     
  408.     def xpath(self):
  409.         paths = [ item.xpath() for item in self.items ]
  410.         return XPathExprOr(paths)
  411.  
  412.  
  413.  
  414. class CombinedSelector(object):
  415.     _method_mapping = {
  416.         ' ': 'descendant',
  417.         '>': 'child',
  418.         '+': 'direct_adjacent',
  419.         '~': 'indirect_adjacent' }
  420.     
  421.     def __init__(self, selector, combinator, subselector):
  422.         self.selector = selector
  423.         self.combinator = combinator
  424.         self.subselector = subselector
  425.  
  426.     
  427.     def __repr__(self):
  428.         if self.combinator == ' ':
  429.             comb = '<followed>'
  430.         else:
  431.             comb = self.combinator
  432.         return '%s[%r %s %r]' % (self.__class__.__name__, self.selector, comb, self.subselector)
  433.  
  434.     
  435.     def xpath(self):
  436.         if self.combinator not in self._method_mapping:
  437.             raise ExpressionError('Unknown combinator: %r' % self.combinator)
  438.         self.combinator not in self._method_mapping
  439.         method = '_xpath_' + self._method_mapping[self.combinator]
  440.         method = getattr(self, method)
  441.         path = self.selector.xpath()
  442.         return method(path, self.subselector)
  443.  
  444.     
  445.     def _xpath_descendant(self, xpath, sub):
  446.         xpath.join('/descendant::', sub.xpath())
  447.         return xpath
  448.  
  449.     
  450.     def _xpath_child(self, xpath, sub):
  451.         xpath.join('/', sub.xpath())
  452.         return xpath
  453.  
  454.     
  455.     def _xpath_direct_adjacent(self, xpath, sub):
  456.         xpath.join('/following-sibling::', sub.xpath())
  457.         xpath.add_name_test()
  458.         xpath.add_condition('position() = 1')
  459.         return xpath
  460.  
  461.     
  462.     def _xpath_indirect_adjacent(self, xpath, sub):
  463.         xpath.join('/following-sibling::', sub.xpath())
  464.         return xpath
  465.  
  466.  
  467. _el_re = re.compile('^\\w+\\s*$', re.UNICODE)
  468. _id_re = re.compile('^(\\w*)#(\\w+)\\s*$', re.UNICODE)
  469. _class_re = re.compile('^(\\w*)\\.(\\w+)\\s*$', re.UNICODE)
  470.  
  471. def css_to_xpath(css_expr, prefix = 'descendant-or-self::'):
  472.     expr = css_expr.xpath()
  473.     if prefix:
  474.         expr.add_prefix(prefix)
  475.     
  476.     return _unicode(expr)
  477.  
  478.  
  479. class XPathExpr(object):
  480.     
  481.     def __init__(self, prefix = None, path = None, element = '*', condition = None, star_prefix = False):
  482.         self.prefix = prefix
  483.         self.path = path
  484.         self.element = element
  485.         self.condition = condition
  486.         self.star_prefix = star_prefix
  487.  
  488.     
  489.     def __str__(self):
  490.         path = ''
  491.         if self.prefix is not None:
  492.             path += _unicode(self.prefix)
  493.         
  494.         if self.path is not None:
  495.             path += _unicode(self.path)
  496.         
  497.         path += _unicode(self.element)
  498.         if self.condition:
  499.             path += '[%s]' % self.condition
  500.         
  501.         return path
  502.  
  503.     
  504.     def __repr__(self):
  505.         return '%s[%s]' % (self.__class__.__name__, self)
  506.  
  507.     
  508.     def add_condition(self, condition):
  509.         if self.condition:
  510.             self.condition = '%s and (%s)' % (self.condition, condition)
  511.         else:
  512.             self.condition = condition
  513.  
  514.     
  515.     def add_path(self, part):
  516.         self.element = part
  517.  
  518.     
  519.     def add_prefix(self, prefix):
  520.         if self.prefix:
  521.             self.prefix = prefix + self.prefix
  522.         else:
  523.             self.prefix = prefix
  524.  
  525.     
  526.     def add_name_test(self):
  527.         if self.element == '*':
  528.             return None
  529.         self.add_condition('name() = %s' % xpath_literal(self.element))
  530.         self.element = '*'
  531.  
  532.     
  533.     def add_star_prefix(self):
  534.         if self.path:
  535.             self.path += '*/'
  536.         else:
  537.             self.path = '*/'
  538.         self.star_prefix = True
  539.  
  540.     
  541.     def join(self, combiner, other):
  542.         prefix = _unicode(self)
  543.         prefix += combiner
  544.         if not other.prefix:
  545.             pass
  546.         if not other.path:
  547.             pass
  548.         path = '' + ''
  549.         if other.star_prefix and path == '*/':
  550.             path = ''
  551.         
  552.         self.prefix = prefix
  553.         self.path = path
  554.         self.element = other.element
  555.         self.condition = other.condition
  556.  
  557.  
  558.  
  559. class XPathExprOr(XPathExpr):
  560.     
  561.     def __init__(self, items, prefix = None):
  562.         for item in items:
  563.             pass
  564.         
  565.         self.items = items
  566.         self.prefix = prefix
  567.  
  568.     
  569.     def __str__(self):
  570.         if not self.prefix:
  571.             pass
  572.         prefix = ''
  573.         return []([ '%s%s' % (prefix, i) for i in self.items ])
  574.  
  575.  
  576. split_at_single_quotes = re.compile("('+)").split
  577.  
  578. def xpath_literal(s):
  579.     if isinstance(s, Element):
  580.         s = s._format_element()
  581.     else:
  582.         s = _unicode(s)
  583.     if "'" not in s:
  584.         s = "'%s'" % s
  585.     elif '"' not in s:
  586.         s = '"%s"' % s
  587.     else:
  588.         s = [] % [](_[1])
  589.     return s
  590.  
  591.  
  592. def parse(string):
  593.     stream = TokenStream(tokenize(string))
  594.     stream.source = string
  595.     
  596.     try:
  597.         return parse_selector_group(stream)
  598.     except SelectorSyntaxError:
  599.         import sys
  600.         e = sys.exc_info()[1]
  601.         message = '%s at %s -> %r' % (e, stream.used, stream.peek())
  602.         e.msg = message
  603.         if sys.version_info < (2, 6):
  604.             e.message = message
  605.         
  606.         e.args = tuple([
  607.             message])
  608.         raise 
  609.  
  610.  
  611.  
  612. def parse_selector_group(stream):
  613.     result = []
  614.     while None:
  615.         if stream.peek() == ',':
  616.             stream.next()
  617.             continue
  618.         break
  619.         continue
  620.         if len(result) == 1:
  621.             return result[0]
  622.         return Or(result)
  623.         return None
  624.  
  625.  
  626. def parse_selector(stream):
  627.     result = parse_simple_selector(stream)
  628.     while None:
  629.         peek = stream.peek()
  630.         if peek == ',' or peek is None:
  631.             return result
  632.         if peek in ('+', '>', '~'):
  633.             combinator = stream.next()
  634.         else:
  635.             combinator = ' '
  636.         consumed = len(stream.used)
  637.         next_selector = parse_simple_selector(stream)
  638.         if consumed == len(stream.used):
  639.             raise SelectorSyntaxError("Expected selector, got '%s'" % stream.peek())
  640.         result = CombinedSelector(result, combinator, next_selector)
  641.         continue
  642.         return result
  643.  
  644.  
  645. def parse_simple_selector(stream):
  646.     peek = stream.peek()
  647.     if peek != '*' and not isinstance(peek, Symbol):
  648.         element = namespace = '*'
  649.     else:
  650.         next = stream.next()
  651.         if next != '*' and not isinstance(next, Symbol):
  652.             raise SelectorSyntaxError("Expected symbol, got '%s'" % next)
  653.         not isinstance(next, Symbol)
  654.         if stream.peek() == '|':
  655.             namespace = next
  656.             stream.next()
  657.             element = stream.next()
  658.             if element != '*' and not isinstance(next, Symbol):
  659.                 raise SelectorSyntaxError("Expected symbol, got '%s'" % next)
  660.             not isinstance(next, Symbol)
  661.         else:
  662.             namespace = '*'
  663.             element = next
  664.     result = Element(namespace, element)
  665.     has_hash = False
  666.     while None:
  667.         peek = stream.peek()
  668.         if peek == '#':
  669.             if has_hash:
  670.                 break
  671.             
  672.             stream.next()
  673.             result = Hash(result, stream.next())
  674.             has_hash = True
  675.             continue
  676.             continue
  677.         if peek == '.':
  678.             stream.next()
  679.             result = Class(result, stream.next())
  680.             continue
  681.             continue
  682.         if peek == '[':
  683.             stream.next()
  684.             result = parse_attrib(result, stream)
  685.             next = stream.next()
  686.             if not next == ']':
  687.                 raise SelectorSyntaxError("] expected, got '%s'" % next)
  688.             next == ']'
  689.             continue
  690.             continue
  691.         if peek == ':' or peek == '::':
  692.             type = stream.next()
  693.             ident = stream.next()
  694.             if not isinstance(ident, Symbol):
  695.                 raise SelectorSyntaxError("Expected symbol, got '%s'" % ident)
  696.             isinstance(ident, Symbol)
  697.             if stream.peek() == '(':
  698.                 stream.next()
  699.                 peek = stream.peek()
  700.                 if isinstance(peek, String):
  701.                     selector = stream.next()
  702.                 elif isinstance(peek, Symbol) and is_int(peek):
  703.                     selector = int(stream.next())
  704.                 else:
  705.                     selector = parse_simple_selector(stream)
  706.                 next = stream.next()
  707.                 if not next == ')':
  708.                     raise SelectorSyntaxError("Expected ')', got '%s' and '%s'" % (next, selector))
  709.                 next == ')'
  710.                 result = Function(result, type, ident, selector)
  711.                 continue
  712.             result = Pseudo(result, type, ident)
  713.             continue
  714.             continue
  715.         if peek == ' ':
  716.             stream.next()
  717.         
  718.         break
  719.         continue
  720.         return result
  721.  
  722.  
  723. def is_int(v):
  724.     
  725.     try:
  726.         int(v)
  727.     except ValueError:
  728.         return False
  729.  
  730.     return True
  731.  
  732.  
  733. def parse_attrib(selector, stream):
  734.     attrib = stream.next()
  735.     if stream.peek() == '|':
  736.         namespace = attrib
  737.         stream.next()
  738.         attrib = stream.next()
  739.     else:
  740.         namespace = '*'
  741.     if stream.peek() == ']':
  742.         return Attrib(selector, namespace, attrib, 'exists', None)
  743.     op = stream.next()
  744.     if op not in ('^=', '$=', '*=', '=', '~=', '|=', '!='):
  745.         raise SelectorSyntaxError("Operator expected, got '%s'" % op)
  746.     op not in ('^=', '$=', '*=', '=', '~=', '|=', '!=')
  747.     value = stream.next()
  748.     if not isinstance(value, (Symbol, String)):
  749.         raise SelectorSyntaxError("Expected string or symbol, got '%s'" % value)
  750.     isinstance(value, (Symbol, String))
  751.     return Attrib(selector, namespace, attrib, op, value)
  752.  
  753.  
  754. def parse_series(s):
  755.     if isinstance(s, Element):
  756.         s = s._format_element()
  757.     
  758.     if not s or s == '*':
  759.         return (0, 0)
  760.     if isinstance(s, int):
  761.         return (0, s)
  762.     if s == 'odd':
  763.         return (2, 1)
  764.     if s == 'even':
  765.         return (2, 0)
  766.     if s == 'n':
  767.         return (1, 0)
  768.     if 'n' not in s:
  769.         return (0, int(s))
  770.     (a, b) = s.split('n', 1)
  771.     if not a:
  772.         a = 1
  773.     elif a == '-' or a == '+':
  774.         a = int(a + '1')
  775.     else:
  776.         a = int(a)
  777.     if not b:
  778.         b = 0
  779.     elif b == '-' or b == '+':
  780.         b = int(b + '1')
  781.     else:
  782.         b = int(b)
  783.     return (a, b)
  784.  
  785. _whitespace_re = re.compile('\\s+', re.UNICODE)
  786. _comment_re = re.compile('/\\*.*?\\*/', re.DOTALL)
  787. _count_re = re.compile('[+-]?\\d*n(?:[+-]\\d+)?')
  788.  
  789. def tokenize(s):
  790.     pos = 0
  791.     s = _comment_re.sub('', s)
  792.     while None:
  793.         match = _whitespace_re.match(s, pos = pos)
  794.         if match:
  795.             preceding_whitespace_pos = pos
  796.             pos = match.end()
  797.         else:
  798.             preceding_whitespace_pos = 0
  799.         if pos >= len(s):
  800.             return None
  801.         match = _count_re.match(s, pos = pos)
  802.         c = s[pos]
  803.         c2 = s[pos:pos + 2]
  804.         old_pos = pos
  805.         (sym, pos) = tokenize_symbol(s, pos)
  806.         yield Symbol(sym, old_pos)
  807.         continue
  808.         continue
  809.         return None
  810.  
  811. split_at_string_escapes = re.compile('(\\\\(?:%s))' % '|'.join([
  812.     '[A-Fa-f0-9]{1,6}(?:\r\n|\\s)?',
  813.     '[^A-Fa-f0-9]'])).split
  814.  
  815. def unescape_string_literal(literal):
  816.     substrings = []
  817.     for substring in split_at_string_escapes(literal):
  818.         if not substring:
  819.             continue
  820.         elif '\\' in substring:
  821.             if substring[0] == '\\' and len(substring) > 1:
  822.                 substring = substring[1:]
  823.                 if substring[0] in '0123456789ABCDEFabcdef':
  824.                     substring = _unichr(int(substring, 16))
  825.                 
  826.             else:
  827.                 raise SelectorSyntaxError('Invalid escape sequence %r in string %r' % (substring.split('\\')[1], literal))
  828.         len(substring) > 1
  829.         substrings.append(substring)
  830.     
  831.     return ''.join(substrings)
  832.  
  833.  
  834. def tokenize_escaped_string(s, pos):
  835.     quote = s[pos]
  836.     pos = pos + 1
  837.     start = pos
  838.     while None:
  839.         next = s.find(quote, pos)
  840.         if next == -1:
  841.             raise SelectorSyntaxError('Expected closing %s for string in: %r' % (quote, s[start:]))
  842.         result = s[start:next]
  843.         if result.endswith('\\'):
  844.             pos = next + 1
  845.             continue
  846.         
  847.         if '\\' in result:
  848.             result = unescape_string_literal(result)
  849.         
  850.         return (result, next + 1)
  851.         return None
  852.  
  853. _illegal_symbol = re.compile('[^\\w\\\\-]', re.UNICODE)
  854.  
  855. def tokenize_symbol(s, pos):
  856.     start = pos
  857.     match = _illegal_symbol.search(s, pos = pos)
  858.     if not match:
  859.         return (s[start:], len(s))
  860.     if match.start() == pos:
  861.         pass
  862.     
  863.     if not match:
  864.         result = s[start:]
  865.         pos = len(s)
  866.     else:
  867.         result = s[start:match.start()]
  868.         pos = match.start()
  869.     
  870.     try:
  871.         result = result.encode('ASCII', 'backslashreplace').decode('unicode_escape')
  872.     except UnicodeDecodeError:
  873.         import sys
  874.         e = sys.exc_info()[1]
  875.         raise SelectorSyntaxError('Bad symbol %r: %s' % (result, e))
  876.  
  877.     return (result, pos)
  878.  
  879.  
  880. class TokenStream(object):
  881.     
  882.     def __init__(self, tokens, source = None):
  883.         self.used = []
  884.         self.tokens = iter(tokens)
  885.         self.source = source
  886.         self.peeked = None
  887.         self._peeking = False
  888.         
  889.         try:
  890.             self.next_token = self.tokens.next
  891.         except AttributeError:
  892.             self.next_token = self.tokens.__next__
  893.  
  894.  
  895.     
  896.     def next(self):
  897.         if self._peeking:
  898.             self._peeking = False
  899.             self.used.append(self.peeked)
  900.             return self.peeked
  901.         
  902.         try:
  903.             next = self.next_token()
  904.             self.used.append(next)
  905.             return next
  906.         except StopIteration:
  907.             self._peeking
  908.             self._peeking
  909.             return None
  910.  
  911.  
  912.     
  913.     def __iter__(self):
  914.         return iter(self.next, None)
  915.  
  916.     
  917.     def peek(self):
  918.         if not self._peeking:
  919.             
  920.             try:
  921.                 self.peeked = self.next_token()
  922.             except StopIteration:
  923.                 return None
  924.  
  925.             self._peeking = True
  926.         
  927.         return self.peeked
  928.  
  929.  
  930.