home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 October / maximum-cd-2011-10.iso / DiscContents / digsby_setup.exe / lib / lxml / cssselect.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-06-22  |  26.5 KB  |  891 lines

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