Subversion Repositories Kolibri OS

Rev

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

  1. class Token:
  2.     def __init__(self,pos=(0,0),type='symbol',val=None,items=None):
  3.         self.pos,self.type,self.val,self.items=pos,type,val,items
  4.  
  5. def u_error(ctx,s,i):
  6.     y,x = i
  7.     line = s.split('\n')[y-1]
  8.     p = ''
  9.     if y < 10: p += ' '
  10.     if y < 100: p += '  '
  11.     r = p + str(y) + ": " + line + "\n"
  12.     r += "     "+" "*x+"^" +'\n'
  13.     raise 'error: '+ctx+'\n'+r
  14.  
  15. ISYMBOLS = '`-=[];,./~!@$%^&*()+{}:<>?|'
  16. SYMBOLS = [
  17.     'def','class','yield','return','pass','and','or','not','in','import',
  18.     'is','while','break','for','continue','if','else','elif','try',
  19.     'except','raise','True','False','None','global','del','from',
  20.     '-','+','*','**','/','%','<<','>>',
  21.     '-=','+=','*=','/=','=','==','!=','<','>', '|=', '&=', '^=',
  22.     '<=','>=','[',']','{','}','(',')','.',':',',',';','&','|','!', '^'
  23.     ]
  24. B_BEGIN,B_END = ['[','(','{'],[']',')','}']
  25.  
  26. class TData:
  27.     def __init__(self):
  28.         self.y,self.yi,self.nl = 1,0,True
  29.         self.res,self.indent,self.braces = [],[0],0
  30.     def add(self,t,v): self.res.append(Token(self.f,t,v))
  31.  
  32. def clean(s):
  33.     s = s.replace('\r\n','\n')
  34.     s = s.replace('\r','\n')
  35.     return s
  36.  
  37. def tokenize(s):
  38.     global T
  39.     s = clean(s)
  40.     T,i,l = TData(),0,len(s)
  41.     try: return do_tokenize(s,i,l)
  42.     except: u_error('tokenize',s,T.f)
  43.  
  44. def do_tokenize(s,i,l):
  45.     global T
  46.     T.f = (T.y,i-T.yi+1)
  47.     while i < l:
  48.         c = s[i]; T.f = (T.y,i-T.yi+1)
  49.         if T.nl: T.nl = False; i = do_indent(s,i,l)
  50.         elif c == '\n': i = do_nl(s,i,l)
  51.         elif c in ISYMBOLS: i = do_symbol(s,i,l)
  52.         elif c >= '0' and c <= '9': i = do_number(s,i,l)
  53.         elif (c >= 'a' and c <= 'z') or \
  54.             (c >= 'A' and c <= 'Z') or c == '_':  i = do_name(s,i,l)
  55.         elif c=='"' or c=="'": i = do_string(s,i,l)
  56.         elif c=='#': i = do_comment(s,i,l)
  57.         elif c == '\\' and s[i+1] == '\n':
  58.             i += 2; T.y,T.yi = T.y+1,i
  59.         elif c == ' ' or c == '\t': i += 1
  60.         else: u_error('tokenize',s,T.f)
  61.     indent(0)
  62.     r = T.res; T = None
  63.     #for t in r:
  64.         #print (t.pos,t.type,t.val)
  65.     return r
  66.  
  67. def do_nl(s,i,l):
  68.     if not T.braces:
  69.         T.add('nl',None)
  70.     i,T.nl = i+1,True
  71.     T.y,T.yi = T.y+1,i
  72.     return i
  73.  
  74. def do_indent(s,i,l):
  75.     v = 0
  76.     while i<l:
  77.         c = s[i]
  78.         if c != ' ' and c != '\t': break
  79.         i,v = i+1,v+1
  80.     if c != '\n' and c != '#' and not T.braces: indent(v)
  81.     return i
  82.  
  83. def indent(v):
  84.     if v == T.indent[-1]: pass
  85.     elif v > T.indent[-1]:
  86.         T.indent.append(v)
  87.         T.add('indent',v)
  88.     elif v < T.indent[-1]:
  89.         n = T.indent.index(v)
  90.         while len(T.indent) > n+1:
  91.             v = T.indent.pop()
  92.             T.add('dedent',v)
  93.  
  94. def do_symbol(s,i,l):
  95.     symbols = []
  96.     v,f,i = s[i],i,i+1
  97.     if v in SYMBOLS: symbols.append(v)
  98.     while i<l:
  99.         c = s[i]
  100.         if not c in ISYMBOLS: break
  101.         v,i = v+c,i+1
  102.         if v in SYMBOLS: symbols.append(v)
  103.     v = symbols.pop(); n = len(v); i = f+n
  104.     T.add('symbol',v)
  105.     if v in B_BEGIN: T.braces += 1
  106.     if v in B_END: T.braces -= 1
  107.     return i
  108.  
  109. def do_number(s,i,l):
  110.     v,i,c =s[i],i+1,s[i]
  111.     while i<l:
  112.         c = s[i]
  113.         if (c < '0' or c > '9') and (c < 'a' or c > 'f') and c != 'x': break
  114.         v,i = v+c,i+1
  115.     if c == '.':
  116.         v,i = v+c,i+1
  117.         while i<l:
  118.             c = s[i]
  119.             if c < '0' or c > '9': break
  120.             v,i = v+c,i+1
  121.     T.add('number',v)
  122.     return i
  123.  
  124. def do_name(s,i,l):
  125.     v,i =s[i],i+1
  126.     while i<l:
  127.         c = s[i]
  128.         if (c < 'a' or c > 'z') and (c < 'A' or c > 'Z') and (c < '0' or c > '9') and c != '_': break
  129.         v,i = v+c,i+1
  130.     if v in SYMBOLS: T.add('symbol',v)
  131.     else: T.add('name',v)
  132.     return i
  133.  
  134. def do_string(s,i,l):
  135.     v,q,i = '',s[i],i+1
  136.     if (l-i) >= 5 and s[i] == q and s[i+1] == q: # """
  137.         i += 2
  138.         while i<l-2:
  139.             c = s[i]
  140.             if c == q and s[i+1] == q and s[i+2] == q:
  141.                 i += 3
  142.                 T.add('string',v)
  143.                 break
  144.             else:
  145.                 v,i = v+c,i+1
  146.                 if c == '\n': T.y,T.yi = T.y+1,i
  147.     else:
  148.         while i<l:
  149.             c = s[i]
  150.             if c == "\\":
  151.                 i = i+1; c = s[i]
  152.                 if c == "n": c = '\n'
  153.                 if c == "r": c = chr(13)
  154.                 if c == "t": c = "\t"
  155.                 if c == "0": c = "\0"
  156.                 v,i = v+c,i+1
  157.             elif c == q:
  158.                 i += 1
  159.                 T.add('string',v)
  160.                 break
  161.             else:
  162.                 v,i = v+c,i+1
  163.     return i
  164.  
  165. def do_comment(s,i,l):
  166.     i += 1
  167.     while i<l:
  168.         c = s[i]
  169.         if c == '\n': break
  170.         i += 1
  171.     return i
  172.  
  173.  
  174.