forked from KolibriOS/kolibrios
Uploaded tinypy sources.
git-svn-id: svn://kolibrios.org@1913 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
408
programs/develop/tinypy/tinypy/parse.py
Normal file
408
programs/develop/tinypy/tinypy/parse.py
Normal file
@@ -0,0 +1,408 @@
|
||||
import tokenize
|
||||
from tokenize import Token
|
||||
if '.' in str(1.0):
|
||||
from boot import *
|
||||
|
||||
def check(t,*vs):
|
||||
if vs[0] == None: return True
|
||||
if t.type in vs: return True
|
||||
if t.type == 'symbol' and t.val in vs: return True
|
||||
return False
|
||||
|
||||
def tweak(k,v):
|
||||
P.stack.append((k,dmap[k]))
|
||||
if v: dmap[k] = omap[k]
|
||||
else: dmap[k] = {'lbp':0,'nud':itself}
|
||||
def restore():
|
||||
k,v = P.stack.pop()
|
||||
dmap[k] = v
|
||||
|
||||
def cpy(d):
|
||||
r = {}
|
||||
for k in d: r[k] = d[k]
|
||||
return r
|
||||
|
||||
class PData:
|
||||
def __init__(self,s,tokens):
|
||||
self.s = s
|
||||
self.tokens = tokens
|
||||
self.pos = 0
|
||||
self.token = None
|
||||
self.stack = []
|
||||
def init(self):
|
||||
global omap,dmap
|
||||
omap = cpy(base_dmap)
|
||||
dmap = cpy(base_dmap)
|
||||
self.advance()
|
||||
def advance(self,val=None):
|
||||
if not check(self.token,val):
|
||||
error('expected '+val,self.token)
|
||||
if self.pos < len(self.tokens):
|
||||
t = self.tokens[self.pos]
|
||||
self.pos += 1
|
||||
else:
|
||||
t = Token((0,0),'eof','eof')
|
||||
self.token = do(t)
|
||||
return t
|
||||
def error(ctx,t):
|
||||
print t
|
||||
tokenize.u_error(ctx,P.s,t.pos)
|
||||
|
||||
def nud(t):
|
||||
#if 'nud' not in t:
|
||||
# error('no nud',t)
|
||||
return t.nud(t)
|
||||
def led(t,left):
|
||||
#if 'led' not in t:
|
||||
# error('no led',t)
|
||||
return t.led(t,left)
|
||||
def get_lbp(t):
|
||||
#if 'lbp' not in t:
|
||||
# error('no lbp',t)
|
||||
return t.lbp
|
||||
def get_items(t):
|
||||
#if 'items' not in t:
|
||||
# error('no items',t)
|
||||
return t.items
|
||||
|
||||
def expression(rbp):
|
||||
t = P.token
|
||||
advance()
|
||||
left = nud(t)
|
||||
while rbp < get_lbp(P.token):
|
||||
t = P.token
|
||||
advance()
|
||||
left = led(t,left)
|
||||
return left
|
||||
|
||||
def infix_led(t,left):
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_is(t,left):
|
||||
if check(P.token,'not'):
|
||||
t.val = 'isnot'
|
||||
advance('not')
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_not(t,left):
|
||||
advance('in')
|
||||
t.val = 'notin'
|
||||
t.items = [left,expression(t.bp)]
|
||||
return t
|
||||
def infix_tuple(t,left):
|
||||
r = expression(t.bp)
|
||||
if left.val == ',':
|
||||
left.items.append(r)
|
||||
return left
|
||||
t.items = [left,r]
|
||||
t.type = 'tuple'
|
||||
return t
|
||||
def lst(t):
|
||||
if t == None: return []
|
||||
if check(t,',','tuple','statements'):
|
||||
return get_items(t)
|
||||
return [t]
|
||||
def ilst(typ,t):
|
||||
return Token(t.pos,typ,typ,lst(t))
|
||||
|
||||
def call_led(t,left):
|
||||
r = Token(t.pos,'call','$',[left])
|
||||
while not check(P.token,')'):
|
||||
tweak(',',0)
|
||||
r.items.append(expression(0))
|
||||
if P.token.val == ',': advance(',')
|
||||
restore()
|
||||
advance(")")
|
||||
return r
|
||||
def get_led(t,left):
|
||||
r = Token(t.pos,'get','.',[left])
|
||||
items = [left]
|
||||
more = False
|
||||
while not check(P.token,']'):
|
||||
more = False
|
||||
if check(P.token,':'):
|
||||
items.append(Token(P.token.pos,'symbol','None'))
|
||||
else:
|
||||
items.append(expression(0))
|
||||
if check(P.token,':'):
|
||||
advance(':')
|
||||
more = True
|
||||
if more:
|
||||
items.append(Token(P.token.pos,'symbol','None'))
|
||||
if len(items) > 2:
|
||||
items = [left,Token(t.pos,'slice',':',items[1:])]
|
||||
r.items = items
|
||||
advance("]")
|
||||
return r
|
||||
def dot_led(t,left):
|
||||
r = expression(t.bp)
|
||||
r.type = 'string'
|
||||
t.items = [left,r]
|
||||
return t
|
||||
|
||||
def itself(t):
|
||||
return t
|
||||
def paren_nud(t):
|
||||
tweak(',',1)
|
||||
r = expression(0)
|
||||
restore()
|
||||
advance(')')
|
||||
return r
|
||||
def list_nud(t):
|
||||
t.type = 'list'
|
||||
t.val = '[]'
|
||||
t.items = []
|
||||
next = P.token
|
||||
tweak(',',0)
|
||||
while not check(P.token,'for',']'):
|
||||
r = expression(0)
|
||||
t.items.append(r)
|
||||
if P.token.val == ',': advance(',')
|
||||
if check(P.token,'for'):
|
||||
t.type = 'comp'
|
||||
advance('for')
|
||||
tweak('in',0)
|
||||
t.items.append(expression(0))
|
||||
advance('in')
|
||||
t.items.append(expression(0))
|
||||
restore()
|
||||
restore()
|
||||
advance(']')
|
||||
return t
|
||||
def dict_nud(t):
|
||||
t.type='dict'
|
||||
t.val = '{}'
|
||||
t.items = []
|
||||
tweak(',',0)
|
||||
while not check(P.token,'}'):
|
||||
t.items.append(expression(0))
|
||||
if check(P.token,':',','): advance()
|
||||
restore()
|
||||
advance('}')
|
||||
return t
|
||||
|
||||
def advance(t=None):
|
||||
return P.advance(t)
|
||||
|
||||
def block():
|
||||
items = []
|
||||
tok = P.token
|
||||
|
||||
while check(P.token,'nl'): advance()
|
||||
if check(P.token,'indent'):
|
||||
advance('indent')
|
||||
while not check(P.token,'dedent'):
|
||||
items.append(expression(0))
|
||||
while check(P.token,';','nl'): advance()
|
||||
advance('dedent')
|
||||
else:
|
||||
items.append(expression(0))
|
||||
while check(P.token,';'):
|
||||
advance(';')
|
||||
items.append(expression(0))
|
||||
while check(P.token,'nl'): advance()
|
||||
|
||||
if len(items) > 1:
|
||||
return Token(tok.pos,'statements',';',items)
|
||||
return items.pop()
|
||||
|
||||
def def_nud(t):
|
||||
items = t.items = []
|
||||
items.append(P.token); advance()
|
||||
advance('(')
|
||||
r = Token(t.pos,'symbol','():',[])
|
||||
items.append(r)
|
||||
while not check(P.token,')'):
|
||||
tweak(',',0)
|
||||
r.items.append(expression(0))
|
||||
if check(P.token,','): advance(',')
|
||||
restore()
|
||||
advance(')')
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
|
||||
|
||||
def while_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
def class_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance(':')
|
||||
items.append(ilst('methods',block()))
|
||||
return t
|
||||
|
||||
def from_nud(t):
|
||||
items = t.items = []
|
||||
items.append(expression(0))
|
||||
advance('import')
|
||||
items.append(expression(0))
|
||||
return t
|
||||
|
||||
def for_nud(t):
|
||||
items = t.items = []
|
||||
tweak('in',0)
|
||||
items.append(expression(0))
|
||||
advance('in')
|
||||
items.append(expression(0))
|
||||
restore()
|
||||
advance(':')
|
||||
items.append(block())
|
||||
return t
|
||||
def if_nud(t):
|
||||
items = t.items = []
|
||||
a = expression(0)
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(t.pos,'elif','elif',[a,b]))
|
||||
while check(P.token,'elif'):
|
||||
tok = P.token
|
||||
advance('elif')
|
||||
a = expression(0)
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'elif','elif',[a,b]))
|
||||
if check(P.token,'else'):
|
||||
tok = P.token
|
||||
advance('else')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'else','else',[b]))
|
||||
return t
|
||||
def try_nud(t):
|
||||
items = t.items = []
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(b)
|
||||
while check(P.token,'except'):
|
||||
tok = P.token
|
||||
advance('except')
|
||||
if not check(P.token,':'): a = expression(0)
|
||||
else: a = Token(tok.pos,'symbol','None')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'except','except',[a,b]))
|
||||
if check(P.token,'else'):
|
||||
tok = P.token
|
||||
advance('else')
|
||||
advance(':')
|
||||
b = block()
|
||||
items.append(Token(tok.pos,'else','else',[b]))
|
||||
return t
|
||||
def prefix_nud(t):
|
||||
#bp = 70
|
||||
#if 'bp' in t: bp = t['bp']
|
||||
bp = t.bp
|
||||
t.items = [expression(bp)]
|
||||
return t
|
||||
def prefix_nud0(t):
|
||||
if check(P.token,'nl',';','eof','dedent'): return t
|
||||
return prefix_nud(t)
|
||||
def prefix_nuds(t):
|
||||
r = expression(0)
|
||||
return ilst(t.type,r)
|
||||
|
||||
def prefix_neg(t):
|
||||
r = expression(50)
|
||||
if r.type == 'number':
|
||||
r.val = str(-float(r.val))
|
||||
return r
|
||||
t.items = [Token(t.pos,'number','0'),r]
|
||||
return t
|
||||
def vargs_nud(t):
|
||||
r = prefix_nud(t)
|
||||
t.type = 'args'
|
||||
t.val = '*'
|
||||
return t
|
||||
def nargs_nud(t):
|
||||
r = prefix_nud(t)
|
||||
t.type = 'nargs'
|
||||
t.val = '**'
|
||||
return t
|
||||
|
||||
|
||||
base_dmap = {
|
||||
',':{'lbp':20,'bp':20,'led':infix_tuple},
|
||||
'+':{'lbp':50,'bp':50,'led':infix_led},
|
||||
'-':{'lbp':50,'nud':prefix_neg,
|
||||
'bp':50,'led':infix_led},
|
||||
'not':{'lbp':35,'nud':prefix_nud,'bp':35,
|
||||
'bp':35,'led':infix_not },
|
||||
'%':{'lbp':60,'bp':60,'led':infix_led},
|
||||
'*':{'lbp':60,'nud':vargs_nud,
|
||||
'bp':60,'led':infix_led,},
|
||||
'**': {'lbp':65,'nud':nargs_nud,
|
||||
'bp':65,'led':infix_led,},
|
||||
'/':{'lbp':60,'bp':60,'led':infix_led},
|
||||
'(':{'lbp':70,'nud':paren_nud,
|
||||
'bp':80,'led':call_led,},
|
||||
'[':{'lbp':70,'nud':list_nud,
|
||||
'bp':80,'led':get_led,},
|
||||
'{':{'lbp':0,'nud':dict_nud,},
|
||||
'.':{'lbp':80,'bp':80,'led':dot_led,'type':'get',},
|
||||
'break':{'lbp':0,'nud':itself,'type':'break'},
|
||||
'pass':{'lbp':0,'nud':itself,'type':'pass'},
|
||||
'continue':{'lbp':0,'nud':itself,'type':'continue'},
|
||||
'eof':{'lbp':0,'type':'eof','val':'eof'},
|
||||
'def':{'lbp':0,'nud':def_nud,'type':'def',},
|
||||
'while':{'lbp':0,'nud':while_nud,'type':'while',},
|
||||
'for':{'lbp':0,'nud':for_nud,'type':'for',},
|
||||
'try':{'lbp':0,'nud':try_nud,'type':'try',},
|
||||
'if':{'lbp':0,'nud':if_nud,'type':'if',},
|
||||
'class':{'lbp':0,'nud':class_nud,'type':'class',},
|
||||
'raise':{'lbp':0,'nud':prefix_nud0,'type':'raise','bp':20,},
|
||||
'return':{'lbp':0,'nud':prefix_nud0,'type':'return','bp':10,},
|
||||
'import':{'lbp':0,'nud':prefix_nuds,'type':'import','bp':20,},
|
||||
'from':{'lbp':0,'nud':from_nud,'type':'from','bp':20,},
|
||||
'del':{'lbp':0,'nud':prefix_nuds,'type':'del','bp':10,},
|
||||
'global':{'lbp':0,'nud':prefix_nuds,'type':'globals','bp':20,},
|
||||
|
||||
'=':{
|
||||
'lbp':10,'bp':9,'led':infix_led,
|
||||
},
|
||||
}
|
||||
|
||||
def i_infix(bp,led,*vs):
|
||||
for v in vs: base_dmap[v] = {'lbp':bp,'bp':bp,'led':led}
|
||||
i_infix(40,infix_led,'<','>','<=','>=','!=','==')
|
||||
i_infix(40,infix_is,'is','in')
|
||||
i_infix(10,infix_led,'+=','-=','*=','/=')
|
||||
i_infix(31,infix_led,'and','&')
|
||||
i_infix(30,infix_led,'or','|')
|
||||
i_infix(36,infix_led,'<<','>>')
|
||||
def i_terms(*vs):
|
||||
for v in vs: base_dmap[v] = {'lbp':0,'nud':itself}
|
||||
i_terms(')','}',']',';',':','nl','elif','else','True','False','None','name','string','number','indent','dedent','except')
|
||||
base_dmap['nl']['val'] = 'nl'
|
||||
|
||||
def gmap(t,v):
|
||||
if v not in dmap:
|
||||
error('unknown "%s"'%v,t)
|
||||
return dmap[v]
|
||||
|
||||
def do(t):
|
||||
if t.type == 'symbol': r = gmap(t,t.val)
|
||||
else: r = gmap(t,t.type)
|
||||
merge(t,r)
|
||||
return t
|
||||
def do_module():
|
||||
tok = P.token
|
||||
items = []
|
||||
while not check(P.token,'eof'):
|
||||
items.append(block())
|
||||
if len(items) > 1:
|
||||
return Token(tok.pos,'statements',';',items)
|
||||
return items.pop()
|
||||
|
||||
def parse(s,tokens,wrap=0):
|
||||
global P
|
||||
s = tokenize.clean(s)
|
||||
P=PData(s,tokens); P.init()
|
||||
r = do_module()
|
||||
P = None
|
||||
return r
|
||||
|
Reference in New Issue
Block a user