Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. import tokenize
  2. from tokenize import Token
  3. if '.' in str(1.0):
  4.     from boot import *
  5.  
  6. def check(t,*vs):
  7.     if vs[0] == None: return True
  8.     if t.type in vs: return True
  9.     if t.type == 'symbol' and t.val in vs: return True
  10.     return False
  11.  
  12. def tweak(k,v):
  13.     P.stack.append((k,dmap[k]))
  14.     if v: dmap[k] = omap[k]
  15.     else: dmap[k] = {'lbp':0,'nud':itself}
  16. def restore():
  17.     k,v = P.stack.pop()
  18.     dmap[k] = v
  19.  
  20. def cpy(d):
  21.     r = {}
  22.     for k in d: r[k] = d[k]
  23.     return r
  24.  
  25. class PData:
  26.     def __init__(self,s,tokens):
  27.         self.s = s
  28.         self.tokens = tokens
  29.         self.pos = 0
  30.         self.token = None
  31.         self.stack = []
  32.     def init(self):
  33.         global omap,dmap
  34.         omap = cpy(base_dmap)
  35.         dmap = cpy(base_dmap)
  36.         self.advance()
  37.     def advance(self,val=None):
  38.         if not check(self.token,val):
  39.             error('expected '+val,self.token)
  40.         if self.pos < len(self.tokens):
  41.             t = self.tokens[self.pos]
  42.             self.pos += 1
  43.         else:
  44.             t = Token((0,0),'eof','eof')
  45.         self.token = do(t)
  46.         return t
  47. def error(ctx,t):
  48.     print t
  49.     tokenize.u_error(ctx,P.s,t.pos)
  50.  
  51. def nud(t):
  52.     #if 'nud' not in t:
  53.     #    error('no nud',t)
  54.     return t.nud(t)
  55. def led(t,left):
  56.     #if 'led' not in t:
  57.     #    error('no led',t)
  58.     return t.led(t,left)
  59. def get_lbp(t):
  60.     #if 'lbp' not in t:
  61.     #    error('no lbp',t)
  62.     return t.lbp
  63. def get_items(t):
  64.     #if 'items' not in t:
  65.     #    error('no items',t)
  66.     return t.items
  67.  
  68. def expression(rbp):
  69.     t = P.token
  70.     advance()
  71.     left = nud(t)
  72.     while rbp < get_lbp(P.token):
  73.         t = P.token
  74.         advance()
  75.         left = led(t,left)
  76.     return left
  77.  
  78. def infix_led(t,left):
  79.     t.items = [left,expression(t.bp)]
  80.     return t
  81. def infix_is(t,left):
  82.     if check(P.token,'not'):
  83.         t.val = 'isnot'
  84.         advance('not')
  85.     t.items = [left,expression(t.bp)]
  86.     return t
  87. def infix_not(t,left):
  88.     advance('in')
  89.     t.val = 'notin'
  90.     t.items = [left,expression(t.bp)]
  91.     return t
  92. def infix_tuple(t,left):
  93.     r = expression(t.bp)
  94.     if left.val == ',':
  95.         left.items.append(r)
  96.         return left
  97.     t.items = [left,r]
  98.     t.type = 'tuple'
  99.     return t
  100. def lst(t):
  101.     if t == None: return []
  102.     if check(t,',','tuple','statements'):
  103.         return get_items(t)
  104.     return [t]
  105. def ilst(typ,t):
  106.     return Token(t.pos,typ,typ,lst(t))
  107.  
  108. def call_led(t,left):
  109.     r = Token(t.pos,'call','$',[left])
  110.     while not check(P.token,')'):
  111.         tweak(',',0)
  112.         r.items.append(expression(0))
  113.         if P.token.val == ',': advance(',')
  114.         restore()
  115.     advance(")")
  116.     return r
  117. def get_led(t,left):
  118.     r = Token(t.pos,'get','.',[left])
  119.     items =  [left]
  120.     more = False
  121.     while not check(P.token,']'):
  122.         more = False
  123.         if check(P.token,':'):
  124.             items.append(Token(P.token.pos,'symbol','None'))
  125.         else:
  126.             items.append(expression(0))
  127.         if check(P.token,':'):
  128.             advance(':')
  129.             more = True
  130.     if more:
  131.         items.append(Token(P.token.pos,'symbol','None'))
  132.     if len(items) > 2:
  133.         items = [left,Token(t.pos,'slice',':',items[1:])]
  134.     r.items = items
  135.     advance("]")
  136.     return r
  137. def dot_led(t,left):
  138.     r = expression(t.bp)
  139.     r.type = 'string'
  140.     t.items = [left,r]
  141.     return t
  142.  
  143. def itself(t):
  144.     return t
  145. def paren_nud(t):
  146.     tweak(',',1)
  147.     r = expression(0)
  148.     restore()
  149.     advance(')')
  150.     return r
  151. def list_nud(t):
  152.     t.type = 'list'
  153.     t.val = '[]'
  154.     t.items = []
  155.     next = P.token
  156.     tweak(',',0)
  157.     while not check(P.token,'for',']'):
  158.         r = expression(0)
  159.         t.items.append(r)
  160.         if P.token.val == ',': advance(',')
  161.     if check(P.token,'for'):
  162.         t.type = 'comp'
  163.         advance('for')
  164.         tweak('in',0)
  165.         t.items.append(expression(0))
  166.         advance('in')
  167.         t.items.append(expression(0))
  168.         restore()
  169.     restore()
  170.     advance(']')
  171.     return t
  172. def dict_nud(t):
  173.     t.type='dict'
  174.     t.val = '{}'
  175.     t.items = []
  176.     tweak(',',0)
  177.     while not check(P.token,'}'):
  178.         t.items.append(expression(0))
  179.         if check(P.token,':',','): advance()
  180.     restore()
  181.     advance('}')
  182.     return t
  183.  
  184. def advance(t=None):
  185.     return P.advance(t)
  186.  
  187. def block():
  188.     items = []
  189.     tok = P.token
  190.  
  191.     while check(P.token,'nl'): advance()
  192.     if check(P.token,'indent'):
  193.         advance('indent')
  194.         while not check(P.token,'dedent'):
  195.             items.append(expression(0))
  196.             while check(P.token,';','nl'): advance()
  197.         advance('dedent')
  198.     else:
  199.         items.append(expression(0))
  200.         while check(P.token,';'):
  201.             advance(';')
  202.             items.append(expression(0))
  203.     while check(P.token,'nl'): advance()
  204.  
  205.     if len(items) > 1:
  206.         return Token(tok.pos,'statements',';',items)
  207.     return items.pop()
  208.  
  209. def def_nud(t):
  210.     items = t.items = []
  211.     items.append(P.token); advance()
  212.     advance('(')
  213.     r = Token(t.pos,'symbol','():',[])
  214.     items.append(r)
  215.     while not check(P.token,')'):
  216.         tweak(',',0)
  217.         r.items.append(expression(0))
  218.         if check(P.token,','): advance(',')
  219.         restore()
  220.     advance(')')
  221.     advance(':')
  222.     items.append(block())
  223.     return t
  224.  
  225.  
  226. def while_nud(t):
  227.     items = t.items = []
  228.     items.append(expression(0))
  229.     advance(':')
  230.     items.append(block())
  231.     return t
  232. def class_nud(t):
  233.     items = t.items = []
  234.     items.append(expression(0))
  235.     advance(':')
  236.     items.append(ilst('methods',block()))
  237.     return t
  238.  
  239. def from_nud(t):
  240.     items = t.items = []
  241.     items.append(expression(0))
  242.     advance('import')
  243.     items.append(expression(0))
  244.     return t
  245.  
  246. def for_nud(t):
  247.     items = t.items = []
  248.     tweak('in',0)
  249.     items.append(expression(0))
  250.     advance('in')
  251.     items.append(expression(0))
  252.     restore()
  253.     advance(':')
  254.     items.append(block())
  255.     return t
  256. def if_nud(t):
  257.     items = t.items = []
  258.     a = expression(0)
  259.     advance(':')
  260.     b = block()
  261.     items.append(Token(t.pos,'elif','elif',[a,b]))
  262.     while check(P.token,'elif'):
  263.         tok = P.token
  264.         advance('elif')
  265.         a = expression(0)
  266.         advance(':')
  267.         b = block()
  268.         items.append(Token(tok.pos,'elif','elif',[a,b]))
  269.     if check(P.token,'else'):
  270.         tok = P.token
  271.         advance('else')
  272.         advance(':')
  273.         b = block()
  274.         items.append(Token(tok.pos,'else','else',[b]))
  275.     return t
  276. def try_nud(t):
  277.     items = t.items = []
  278.     advance(':')
  279.     b = block()
  280.     items.append(b)
  281.     while check(P.token,'except'):
  282.         tok = P.token
  283.         advance('except')
  284.         if not check(P.token,':'): a = expression(0)
  285.         else: a = Token(tok.pos,'symbol','None')
  286.         advance(':')
  287.         b = block()
  288.         items.append(Token(tok.pos,'except','except',[a,b]))
  289.     if check(P.token,'else'):
  290.         tok = P.token
  291.         advance('else')
  292.         advance(':')
  293.         b = block()
  294.         items.append(Token(tok.pos,'else','else',[b]))
  295.     return t
  296. def prefix_nud(t):
  297.     #bp = 70
  298.     #if 'bp' in t: bp = t['bp']
  299.     bp = t.bp
  300.     t.items = [expression(bp)]
  301.     return t
  302. def prefix_nud0(t):
  303.     if check(P.token,'nl',';','eof','dedent'): return t
  304.     return prefix_nud(t)
  305. def prefix_nuds(t):
  306.     r = expression(0)
  307.     return ilst(t.type,r)
  308.  
  309. def prefix_neg(t):
  310.     r = expression(50)
  311.     if r.type == 'number':
  312.         r.val = str(-float(r.val))
  313.         return r
  314.     t.items = [Token(t.pos,'number','0'),r]
  315.     return t
  316. def vargs_nud(t):
  317.     r = prefix_nud(t)
  318.     t.type = 'args'
  319.     t.val = '*'
  320.     return t
  321. def nargs_nud(t):
  322.     r = prefix_nud(t)
  323.     t.type = 'nargs'
  324.     t.val = '**'
  325.     return t
  326.  
  327.  
  328. base_dmap = {
  329.     ',':{'lbp':20,'bp':20,'led':infix_tuple},
  330.     '+':{'lbp':50,'bp':50,'led':infix_led},
  331.     '-':{'lbp':50,'nud':prefix_neg,
  332.         'bp':50,'led':infix_led},
  333.     'not':{'lbp':35,'nud':prefix_nud,'bp':35,
  334.         'bp':35,'led':infix_not },
  335.     '%':{'lbp':60,'bp':60,'led':infix_led},
  336.     '*':{'lbp':60,'nud':vargs_nud,
  337.         'bp':60,'led':infix_led,},
  338.     '**': {'lbp':65,'nud':nargs_nud,
  339.         'bp':65,'led':infix_led,},
  340.     '/':{'lbp':60,'bp':60,'led':infix_led},
  341.     '(':{'lbp':70,'nud':paren_nud,
  342.         'bp':80,'led':call_led,},
  343.     '[':{'lbp':70,'nud':list_nud,
  344.         'bp':80,'led':get_led,},
  345.     '{':{'lbp':0,'nud':dict_nud,},
  346.     '.':{'lbp':80,'bp':80,'led':dot_led,'type':'get',},
  347.     'break':{'lbp':0,'nud':itself,'type':'break'},
  348.     'pass':{'lbp':0,'nud':itself,'type':'pass'},
  349.     'continue':{'lbp':0,'nud':itself,'type':'continue'},
  350.     'eof':{'lbp':0,'type':'eof','val':'eof'},
  351.     'def':{'lbp':0,'nud':def_nud,'type':'def',},
  352.     'while':{'lbp':0,'nud':while_nud,'type':'while',},
  353.     'for':{'lbp':0,'nud':for_nud,'type':'for',},
  354.     'try':{'lbp':0,'nud':try_nud,'type':'try',},
  355.     'if':{'lbp':0,'nud':if_nud,'type':'if',},
  356.     'class':{'lbp':0,'nud':class_nud,'type':'class',},
  357.     'raise':{'lbp':0,'nud':prefix_nud0,'type':'raise','bp':20,},
  358.     'return':{'lbp':0,'nud':prefix_nud0,'type':'return','bp':10,},
  359.     'import':{'lbp':0,'nud':prefix_nuds,'type':'import','bp':20,},
  360.     'from':{'lbp':0,'nud':from_nud,'type':'from','bp':20,},
  361.     'del':{'lbp':0,'nud':prefix_nuds,'type':'del','bp':10,},
  362.     'global':{'lbp':0,'nud':prefix_nuds,'type':'globals','bp':20,},
  363.  
  364.     '=':{
  365.         'lbp':10,'bp':9,'led':infix_led,
  366.         },
  367. }
  368.  
  369. def i_infix(bp,led,*vs):
  370.     for v in vs: base_dmap[v] = {'lbp':bp,'bp':bp,'led':led}
  371. i_infix(40,infix_led,'<','>','<=','>=','!=','==')
  372. i_infix(40,infix_is,'is','in')
  373. i_infix(10,infix_led,'+=','-=','*=','/=')
  374. i_infix(31,infix_led,'and','&')
  375. i_infix(30,infix_led,'or','|')
  376. i_infix(36,infix_led,'<<','>>')
  377. def i_terms(*vs):
  378.     for v in vs: base_dmap[v] = {'lbp':0,'nud':itself}
  379. i_terms(')','}',']',';',':','nl','elif','else','True','False','None','name','string','number','indent','dedent','except')
  380. base_dmap['nl']['val'] = 'nl'
  381.  
  382. def gmap(t,v):
  383.     if v not in dmap:
  384.         error('unknown "%s"'%v,t)
  385.     return dmap[v]
  386.  
  387. def do(t):
  388.     if t.type == 'symbol': r = gmap(t,t.val)
  389.     else: r = gmap(t,t.type)
  390.     merge(t,r)
  391.     return t
  392. def do_module():
  393.     tok = P.token
  394.     items = []
  395.     while not check(P.token,'eof'):
  396.         items.append(block())
  397.     if len(items) > 1:
  398.         return Token(tok.pos,'statements',';',items)
  399.     return items.pop()
  400.  
  401. def parse(s,tokens,wrap=0):
  402.     global P
  403.     s = tokenize.clean(s)
  404.     P=PData(s,tokens); P.init()
  405.     r = do_module()
  406.     P = None
  407.     return r
  408.  
  409.