zoukankan      html  css  js  c++  java
  • 实现一个编译器(二)

    接上文实现一个编译器

    添加了一些内容:


    1. 支持int,float的除法,以分母为准 4/3为1, 4/3.0为1.333
    2. 单行注释// , 多行注释/* */
    3. 支持闭包, self指代函数本身
    4. 支持++,--,+= -=等
    5. 内置函数len,str, int。内置list,map,值的读取和设置要用[];成员读取要用.
    6. 支持显示的局部变量定义:var a = 1;表示定义a到函数作用域,(只有函数作用域, while if并不是作用域);
    7. 报错显示行号
    8. 无效的变量默认值为False
    9. 字符串对象是只读的,不能通过列表赋值修改

    这些是我认为应该有的功能,每个功能实现也不复杂。

    现在pym看起来更像是一个脚本语言了。

      1 import re
      2 from collections import namedtuple
      3 import functools
      4 
      5 
      6 
      7 #
      8 # __all__ = [
      9 #     "Ready_Registers",
     10 #     "pym_warpper",
     11 #     "patterns",
     12 #     "Token",
     13 #     "Step",
     14 #     "PymError",
     15 #     "PymTokenizeError",
     16 #     "PymStepizeError",
     17 #     "PymBuildinError",
     18 #     "tokenize",
     19 #     "stepize",
     20 #
     21 #     "show_tokens",
     22 #     "show_steps",
     23 #     "show_var",
     24 #     "output_short",
     25 # ]
     26 
     27 Ready_Registers = []
     28 
     29 def pym_warpper(*names):
     30     def dec(func):
     31         @functools.wraps(func)
     32         def swapper(lineno, auto, *arg):
     33             try:
     34                 res = func(*arg) # 执行buildin-function
     35             except PymRunError as ex:
     36                 func_name = auto.namespace.get("__name__", None)
     37                 func_name = "函数"+func_name.value+"" if func_name else ""
     38                 # print("[PythonError]", ex, "(第"+str(lineno)+"行"+func_name+")(大概是因为错误调用了内置函数, 这种错误会直接导致游戏退出)" )
     39                 # raise Exception
     40                 raise PymRunError(str(ex)+"(第"+str(lineno)+""+func_name+")(大概是因为错误调用了内置函数)" )
     41             return res
     42         Ready_Registers.append((names, swapper))
     43         return swapper
     44     return dec
     45 
     46 patterns = [
     47     # ('
    ',        r'(
    )'),
     48 
     49     ('comment', r'(//.*)'),
     50     ('comment', r'(/*[sS]*?*/)'),
     51 
     52     ('cmp',        r'(==)'),
     53     ('cmp',        r'(!=)'),
     54     ('cmp',        r'(>=)'),
     55     ('cmp',        r'(<=)'),
     56     ('cmp',        r'(>)'),
     57     ('cmp',        r'(<)'),
     58 
     59     ('float',        r'(d+.d+)'),
     60     ('int',        r'(d+)'),
     61     ('str',        r"'([^
    ']*)'"),
     62     ('str',        r'"([^
    "]*)"'),
     63 
     64     ('or',        r'(||)'),
     65     ('or',        r'(or)'),
     66     ('and',        r'(&&)'),
     67     ('and',        r'(and)'),
     68 
     69     ('inc',        r'(++)'),
     70     ('dec',        r'(--)'),
     71 
     72     ('assign',    r'(+=)'),
     73     ('assign',    r'(-=)'),
     74     ('assign',    r'(/=)'),
     75     ('assign',    r'(*=)'),
     76     ('assign',    r'(=)'),
     77 
     78     ('+',        r'(+)'),
     79     ('-',        r'(-)'),
     80     ('*',        r'(*)'),
     81     ('/',        r'(/)'),
     82     ('not',        r'(!)'),
     83     ('not',        r'(not)'),
     84     ('print',    r'(print)'),
     85 
     86     (';',        r'(;)'),
     87     (':',        r'(:)'),
     88     (',',        r'(,)'),
     89     ('.',        r'(.)'),
     90     ('(',        r'(()'),
     91     (')',        r'())'),
     92     ('[',        r'([)'),
     93     (']',        r'(])'),
     94     ('{',        r'({)'),
     95     ('}',        r'(})'),
     96 
     97     ('if',        r'(if)'),
     98     ('else',    r'(else)'),
     99     ('for',        r'(for)'),
    100     ('while',    r'(while)'),
    101     ('break',    r'(break)'),
    102     ('continue', r'(continue)'),
    103     ('return',    r'(return)'),
    104     ('function', r'(function)'),
    105     ('True',    r'(True)'),
    106     ('False',    r'(False)'),
    107     ('var',    r'(var)'),
    108 
    109     ('name',    r'([A-Za-z_][w_]*)'),
    110 
    111 ]
    112 
    113 
    114 class Token(namedtuple("Token", ["type", "value", "str", "lineno"])):
    115     def __repr__(self):
    116         return " {0:9} ==>  {1:8} ({2})"
    117             .format(self.type, self.value.replace("
    ", r"
    "), self.str.replace("
    ", r"
    "))
    118 
    119 
    120 class Step(namedtuple("Step", ["type", "value", "lineno"])):
    121     def __repr__(self):
    122         return "[{3}] {0:14} ({2}){1:<12}"
    123             .format(self.type, str(self.value)
    124                 .replace("
    ", r"
    "), str(type(self.value)).replace("<type '", "").replace("'>", ""), self.lineno)
    125 
    126 
    127 class PymError(Exception):
    128     pass
    129 
    130 class PymTokenizeError(PymError):
    131     pass
    132 
    133 class PymStepizeError(PymError):
    134     pass
    135 
    136 class PymRunError( PymError ):
    137     pass
    138 
    139 class Trans(object):
    140     def __init__(self, tokens):
    141         self.i = 0
    142         self.tokens = tokens
    143         self.l = len(tokens)
    144         self.steps = []
    145         self.continue_point = -1
    146         self.break_point = -1
    147 
    148     def pos(self):
    149         return len(self.steps)
    150 
    151     def type(self):
    152         if self.i >= self.l:
    153             return None
    154         return self.tokens[self.i].type
    155 
    156     def prestr(self):
    157         if self.i >= self.l:
    158             return ""
    159         return self.tokens[self.i].str
    160 
    161     def reset(self, pos, value):
    162         lineno = self.tokens[self.i].lineno if self.i<self.l else self.tokens[-1].lineno
    163         self.steps[pos] = Step(self.steps[pos].type, value, lineno)
    164 
    165     def value(self):
    166         if self.i >= self.l:
    167             return None
    168         return self.tokens[self.i].value
    169 
    170     def push(self, t, v=None):
    171         lineno = self.tokens[self.i].lineno if self.i<self.l else self.tokens[-1].lineno
    172         self.steps.append(Step(t, v, lineno))
    173 
    174     def match(self, p):
    175         if self.i >= self.l:
    176             raise PymStepizeError("unexceptable end(第"+str(self.tokens[-1].lineno)+"行)")
    177         if self.tokens[self.i].type != p:
    178             raise PymStepizeError("缺少“"+p+"”(第"+str(self.tokens[self.i].lineno)+"行)")
    179         self.i += 1
    180 
    181     def stmt(self):
    182         if self.type() == ";":
    183             self.match(";")
    184         elif self.type() == "print":
    185             self.i += 1
    186             while 1:
    187                 if self.type() == ';':
    188                     self.i += 1
    189                     break
    190                 self.expr5()
    191                 if self.type() == ',':
    192                     self.i += 1
    193                 elif self.type() == ';':
    194                     self.i += 1
    195                     break
    196                 else:
    197                     raise PymStepizeError("not ok-(第"+str(self.tokens[self.i if self.i<self.l else -1].lineno)+"行)")
    198             self.push("PRINT")
    199         elif self.type() == 'break':
    200             self.break_point = self.pos()
    201             self.push("JUMP")
    202             self.i += 1
    203             self.match(';')
    204         elif self.type() == 'continue':
    205             self.continue_point = self.pos()
    206             self.push("JUMP")
    207             self.i += 1
    208             self.match(';')
    209         elif self.type() == "return":
    210             self.i += 1
    211             if self.type() == ";":
    212                 self.push("PUSH_CONST", None)
    213                 self.i += 1
    214             else:
    215                 self.expr5()
    216                 self.match(';')
    217             self.push("RETURN")
    218         # elif self.type() == 'function':
    219         #     self.i += 1
    220         #     name = ""
    221         #     if self.type() == 'name':
    222         #         self.push("PUSH_LOCAL_VAR",self.value())
    223         #         name = self.value()
    224         #         self.i += 1
    225         #     self.match('(')
    226         #     names = []
    227         #     while 1:
    228         #         if self.type() == 'name':
    229         #             names.append(self.value())
    230         #             self.i += 1
    231         #         else:
    232         #             self.match(')')
    233         #             break
    234         #         if self.type() == ',':
    235         #             self.i += 1
    236         #         elif self.type() == ')':
    237         #             self.i += 1
    238         #             break
    239         #         else:
    240         #             raise PymError("bad function")
    241         #     s = ''
    242         #     self.match('{')
    243         #     count = 1
    244         #     while 1:
    245         #         if self.type() == '{':
    246         #             count += 1
    247         #         elif self.type() == '}':
    248         #             count -= 1
    249         #             if count == 0:
    250         #                 self.i += 1
    251         #                 break
    252         #         s += self.prestr()
    253         #         self.i += 1
    254         #     self.push('PUSH_CONST', s)
    255         #     self.push('PUSH_CONST', names)
    256         #     self.push('MAKE_FUNCTION')
    257         #     if name:
    258         #         self.push("ASSIGN")
    259         elif self.type() == 'if':
    260             self.i += 1
    261             self.match('(')
    262             self.expr5()
    263             self.match(')')
    264             jump_pos = self.pos()
    265             self.push('JUMP_IF_FALSE')
    266             self.block()
    267             if self.type() == 'else':
    268                 self.i += 1
    269                 jump_back_pos = self.pos()
    270                 self.push('JUMP')
    271                 self.reset(jump_pos, self.pos())
    272                 self.block()
    273                 self.reset(jump_back_pos, self.pos())
    274             else:
    275                 self.reset(jump_pos, self.pos())
    276         elif self.type() == 'while':
    277             self.i += 1
    278             self.match('(')
    279             jump_here = self.pos()
    280             self.expr5()
    281             self.match(')')
    282             jump_pos = self.pos()
    283             self.push('JUMP_IF_FALSE')
    284             self.block()
    285             self.push('JUMP', jump_here)
    286             self.reset(jump_pos, self.pos())
    287             if self.break_point != -1:
    288                 self.reset(self.break_point, self.pos())
    289                 self.break_point = -1
    290             if self.continue_point != -1:
    291                 self.reset(self.continue_point, jump_here)
    292                 self.continue_point = -1
    293         elif self.type() == 'var':
    294             self.match('var')
    295             name = self.value()
    296             self.push("PUSH_LOCAL_VAR", name)
    297             self.match('name')
    298             if self.value() != '=':
    299                 raise PymStepizeError('需要“=”(第"+str(self.tokens[self.i].lineno)+"行)')
    300             self.match('assign')
    301             self.expr5()
    302             self.push("ASSIGN")
    303             self.match(';')
    304         else:
    305             self.expr5()
    306             if self.type() == ';':
    307                 self.i += 1
    308             elif self.type() == 'assign':
    309                 t = self.value()
    310                 self.i += 1
    311                 if t != "=":
    312                     self.push("PUSH_LAST_VAR")
    313                 if t == '=':
    314                     self.expr5()
    315                     self.push("ASSIGN")
    316                 elif t == '+=':
    317                     self.expr5()
    318                     self.push("ADD")
    319                     self.push("ASSIGN")
    320                 elif t == '*=':
    321                     self.expr5()
    322                     self.push("MUL")
    323                     self.push("ASSIGN")
    324                 elif t == '-=':
    325                     self.expr5()
    326                     self.push("SUB")
    327                     self.push("ASSIGN")
    328                 elif t == '/=':
    329                     self.expr5()
    330                     self.push("DIV")
    331                     self.push("ASSIGN")
    332                 else:
    333                     raise PymStepizeError("bad assign(第"+str(self.tokens[self.i].lineno)+"行)")
    334                 self.match(';')
    335             elif self.type() == "inc":
    336                 self.i += 1
    337                 self.push("INC")
    338                 self.match(';')
    339             elif self.type() == "dec":
    340                 self.i += 1
    341                 self.push("DEC")
    342                 self.match(';')
    343             self.push("POP_ALL")
    344 
    345     def expr(self):
    346         if self.type() == "int":
    347             self.push("PUSH_CONST", int(self.value()))
    348             self.i += 1
    349         elif self.type() == 'float':
    350             self.push("PUSH_CONST", float(self.value()))
    351             self.i += 1
    352         elif self.type() == "False":
    353             self.push("PUSH_CONST", False)
    354             self.i += 1
    355         elif self.type() == "True":
    356             self.push("PUSH_CONST", True)
    357             self.i += 1
    358         elif self.type() == "not":
    359             self.i += 1
    360             self.expr()
    361             self.push("NOT")
    362         elif self.type() == "-":
    363             self.i += 1
    364             self.expr()
    365             self.push("NEG")
    366         elif self.type() == "str":
    367             self.push("PUSH_CONST", str(self.value()))
    368             self.i += 1
    369         elif self.type() == "name":
    370             self.push("PUSH_VAR", self.value())
    371             self.i += 1
    372         elif self.type() == '(':
    373             self.i += 1
    374             self.expr5()
    375             self.match(")")
    376         elif self.type() == '[':
    377             self.i += 1
    378             count = 0
    379             while self.type() != ']':
    380                 self.expr5()
    381                 count += 1
    382                 if self.type() == ']':
    383                     break
    384                 self.match(',')
    385             self.match(']')
    386             self.push("BUILD_LIST", count)
    387         elif self.type() == '{':
    388             self.i += 1
    389             count = 0
    390             while self.type() != '}':
    391                 self.expr5()
    392                 self.match(':')
    393                 self.expr5()
    394                 count += 1
    395                 if self.type() == '}':
    396                     break
    397                 self.match(',')
    398             self.match('}')
    399             self.push("BUILD_MAP", count)
    400         elif self.type() == 'function':
    401             self.i += 1
    402             name = ""
    403             if self.type() == 'name':
    404                 name = self.value()
    405                 self.push("PUSH_LOCAL_VAR", name)
    406                 self.i += 1
    407             self.match('(')
    408             names = []
    409             while 1:
    410                 if self.type() == 'name':
    411                     names.append(self.value())
    412                     self.i += 1
    413                 else:
    414                     self.match(')')
    415                     break
    416                 if self.type() == ',':
    417                     self.i += 1
    418                 elif self.type() == ')':
    419                     self.i += 1
    420                     break
    421                 else:
    422                     raise PymStepizeError("bad function(第"+str(self.tokens[self.i].lineno)+"行)")
    423             functiontokens = []
    424             self.match('{')
    425             count = 1
    426             while 1:
    427                 if self.type() == '{':
    428                     count += 1
    429                 elif self.type() == '}':
    430                     count -= 1
    431                     if count == 0:
    432                         self.i += 1
    433                         break
    434                 if self.i<self.l:
    435                     functiontokens.append(self.tokens[self.i])
    436                     self.i += 1
    437                 else:
    438                     raise PymStepizeError("bad function(第"+str(self.tokens[self.i].lineno)+"行)")
    439             self.push('PUSH_CONST', stepize(functiontokens))
    440             self.push('PUSH_CONST', names)
    441             self.push('MAKE_FUNCTION')
    442             if name:
    443                 self.push('ASSIGN')
    444         self.name_tail()
    445 
    446     def name_tail(self):
    447         while True:
    448             if self.type() == "(":
    449                 self.i += 1
    450                 count = 0
    451                 while 1:
    452                     if self.type() == ")":
    453                         self.i += 1
    454                         break
    455                     self.expr5()
    456                     count += 1
    457                     if self.type() == ",":
    458                         self.i += 1
    459                     elif self.type() == ")":
    460                         self.i += 1
    461                         break
    462                     else:
    463                         raise PymStepizeError("not ok(第"+str(self.tokens[self.i].lineno)+"行)")
    464                 self.push("CALL", count)
    465             elif self.type() == '[':
    466                 self.i += 1
    467                 self.expr5()
    468                 self.match(']')
    469                 self.push("GET_ITEM")
    470             elif self.type() == '.':
    471                 self.i += 1
    472                 if self.type() != 'name':
    473                     raise PymStepizeError("need a name(第"+str(self.tokens[self.i].lineno)+"行)")
    474                 self.push("PUSH_CONST", self.value())
    475                 self.i += 1
    476                 self.push("GET_METHOD")
    477             elif self.type() == "inc":
    478                 self.i += 1
    479                 self.push("INC")
    480             else:
    481                 break
    482 
    483     def expr1(self):
    484         self.expr()
    485         while self.type() == '*' or self.type() == '/':
    486             t = self.type()
    487             self.i += 1
    488             self.expr()
    489             if t == "*":
    490                 self.push("MUL")
    491             else:
    492                 self.push("DIV")
    493 
    494     def expr2(self):
    495         self.expr1()
    496         while self.type() == '+' or self.type() == '-':
    497             t = self.type()
    498             self.i += 1
    499             self.expr1()
    500             if t == "+":
    501                 self.push("ADD")
    502             else:
    503                 self.push("SUB")
    504 
    505     def expr3(self):
    506         self.expr2()
    507         while self.type() == "cmp":
    508             t = self.value()
    509             self.i += 1
    510             self.expr2()
    511             if t == ">=":
    512                 self.push("GE")
    513             elif t == "<=":
    514                 self.push("LE")
    515             elif t == "<":
    516                 self.push("LT")
    517             elif t == ">":
    518                 self.push("GT")
    519             elif t == "==":
    520                 self.push("EQ")
    521             else:
    522                 self.push("NE")
    523 
    524     def expr4(self):
    525         self.expr3()
    526         while self.type() == 'or' or self.type() == 'and':
    527             t = self.type()
    528             self.i += 1
    529             self.expr3()
    530             if t == "or":
    531                 self.push("OR")
    532             else:
    533                 self.push("AND")
    534 
    535     def expr5(self):
    536         self.expr4()
    537 
    538     def block(self):
    539         if self.type() == '{':
    540             self.i += 1
    541             while self.type() != '}':
    542                 self.stmt()
    543             self.i += 1
    544         else:
    545             self.stmt()
    546 
    547     def eval(self):
    548         while self.i < self.l:
    549             self.stmt()
    550 
    551 def tokenize(buf):
    552     if type(buf) == "str":
    553         raise PymTokenizeError("not a function")
    554     tokens = []
    555     lineno = 1
    556     i = 0
    557     l = len(buf)
    558     while i < l:
    559         prestr = ""
    560         while i < l and buf[i] in " 
    	":
    561             prestr += buf[i]
    562             i += 1
    563         if i >= l:
    564             break
    565         for t, p in patterns:
    566             m = re.match(p, buf[i:])
    567             if m:
    568                 prestr += m.group(0)
    569                 lineno += prestr.count("
    ")
    570                 token = Token(t, m.group(1), prestr, lineno)
    571                 tokens.append(token)
    572                 i += len(m.group(0))
    573                 break
    574         else:
    575             raise PymTokenizeError("不符合任何匹配规则(第"+str(lineno)+"行)")
    576     return tokens
    577 
    578 def stepize(tokens):
    579     # 把tokens里面的注释token去掉
    580     tokens = [token for token in tokens if token.type != 'comment']
    581     t = Trans(tokens)
    582     t.eval()
    583     return t.steps
    pymtoolkit.py
      1 from pymtoolkit import *
      2 
      3 show_tokens = False
      4 show_steps = False
      5 show_var = False
      6 output_short = False
      7 
      8 class Auto(object):
      9 
     10     def __init__(self, value=None, belongto=None, argnames=None, name=None, buildin=None, code=None):
     11         self.value = value if value is not None else False
     12         self.belongto = belongto
     13         self.argnames = argnames or []
     14         self.buildin = buildin
     15         self.tokens = None
     16         self.code = code
     17         if name:
     18             self.namespace = {'self': self, '__name__': Auto(name, belongto=self)}
     19         else:
     20             self.namespace = {'self': self}
     21 
     22         self.steps = []
     23 
     24         self.stack = []
     25         self.l = 0
     26         self.i = 0
     27 
     28     def copy(self):
     29         name = self.namespace.get("__name__", None)
     30         name = name.value if name else ""
     31         auto = Auto(self.value, self.belongto, self.argnames, name=name, buildin=self.buildin, code=self.code)
     32         auto.steps = self.steps
     33 
     34     def __repr__(self):
     35         if self.code:
     36             name = self.namespace.get("__name__", None)
     37             name = name.value if name else ""
     38             s = "<function "+name+">"
     39         else:
     40             s = str(self.value).replace("
    ", r"
    ")
     41         if output_short and len(s) > 15:
     42             return s[:10]+'...'
     43         return s
     44 
     45     def get_name(self):
     46         name = self.namespace.get("__name__", None)
     47         return str(name) if name else ""
     48 
     49     def call(self, args=None, lineno=-1):
     50         if self.buildin is not None:
     51             return self.buildin(lineno, self, args)
     52         self.stack = []
     53         # if not self.code:
     54         #     raise PymError(str(self.namespace["__name__"] or "")
     55         #                    +"不是可执行的函数"+("(第{0}行)".format(lineno) if lineno>=0 else ""))
     56         if args:
     57             for x, y in zip(self.argnames, args):
     58                 y.namespace['__name__'] = Auto(x)
     59                 self.namespace[x] = y
     60         self.namespace["self"] = self
     61 
     62         # funcname = ''
     63         # if not self.steps:
     64         #     funcname = self.namespace.get('__name__', None)
     65         #     funcname = str(funcname.value) if funcname else ""
     66         #     if show_tokens:
     67         #         print("
    [TOKENIZE "+funcname+"]")
     68         #     tokens = tokenize(self.code, lineno)
     69         #     stepstmp = stepize(tokens)
     70         #     if show_steps:
     71         #         print("
    [STEPIZE "+funcname+"]")
     72         #         for i, x in enumerate(stepstmp):
     73         #             print(" {0:3}".format(i), x)
     74         #     self.steps = stepstmp
     75 
     76         # run steps
     77         # if show_var:
     78         #     print("
    [CALL "+funcname+"]")
     79         self.l = len(self.code)
     80         self.i = 0
     81         try:
     82             while self.i < self.l:
     83                 self.step_once()
     84         except PymRunError as e:
     85             raise PymRunError(e)
     86         #     lineno = self.code[self.i].lineno if self.i<self.l else self.code[-1].lineno
     87         #     raise PymRunError(str(e)+"(第"+str(lineno)+"行)")
     88         # if show_var:
     89         #     print("[END "+funcname+"]
    ")
     90 
     91         return self.stack[0] if self.stack else Auto()
     92 
     93     def step_once(self):
     94         t = self.code[self.i]
     95         if show_var:
     96             print(self.i, ":", t)
     97         self.i += 1
     98         if t.type == "PUSH_LAST_VAR":
     99             self.stack.append(self.stack[-1])
    100         elif t.type == "PUSH_VAR":
    101             a = self.namespace.get(t.value)
    102             b = self.belongto
    103             # print("belongto", self.belongto)
    104             while a is None and b is not None:
    105                 a = b.namespace.get(t.value, None)
    106                 b = b.belongto
    107             if a is None:
    108                 a = Auto(None, belongto=self, name=t.value)
    109                 self.namespace[t.value] = a
    110             self.stack.append(a)
    111         elif t.type == "PUSH_LOCAL_VAR":
    112             a = self.namespace.get(t.value)
    113             if a is None:
    114                 a = Auto(None, belongto=self, name=t.value)
    115                 self.namespace[t.value] = a
    116             self.stack.append(a)
    117         elif t.type == "ASSIGN":
    118             value = self.stack.pop()
    119             target = self.stack.pop()
    120             target.value = value.value
    121             # print("[test]", value.belongto)
    122             target.belongto = value.belongto
    123             target.steps = value.steps
    124             target.argnames = value.argnames
    125             target.buildin = value.buildin
    126             target.code = value.code
    127             namespace = value.namespace.copy()
    128             namespace["self"] = target
    129             namespace["__name__"] = target.namespace.get("__name__") or ""
    130             target.namespace = namespace
    131         elif t.type == "PUSH_CONST":
    132             self.stack.append(Auto(t.value, belongto=self))
    133         elif t.type == "POP_ALL":
    134             self.stack = []
    135         elif t.type == "GE":
    136             a = self.stack.pop()
    137             b = self.stack.pop()
    138             self.stack.append(Auto(b.value >= a.value))
    139         elif t.type == "GT":
    140             a = self.stack.pop()
    141             b = self.stack.pop()
    142             self.stack.append(Auto(b.value > a.value))
    143         elif t.type == "LE":
    144             a = self.stack.pop()
    145             b = self.stack.pop()
    146             self.stack.append(Auto(b.value <= a.value))
    147         elif t.type == "LT":
    148             a = self.stack.pop()
    149             b = self.stack.pop()
    150             self.stack.append(Auto(b.value < a.value))
    151         elif t.type == "EQ":
    152             a = self.stack.pop()
    153             b = self.stack.pop()
    154             self.stack.append(Auto(b.value == a.value))
    155         elif t.type == "NE":
    156             a = self.stack.pop()
    157             b = self.stack.pop()
    158             self.stack.append(Auto(b.value != a.value))
    159         elif t.type == "ADD":
    160             a = self.stack.pop()
    161             b = self.stack.pop()
    162             # print("a,b = ",a,b)
    163             self.stack.append(Auto(b.value + a.value))
    164         elif t.type == "SUB":
    165             a = self.stack.pop()
    166             b = self.stack.pop()
    167             self.stack.append(Auto(b.value - a.value))
    168         elif t.type == "MUL":
    169             b = self.stack.pop()
    170             a = self.stack.pop()
    171             self.stack.append(Auto(b.value * a.value))
    172         elif t.type == "DIV":
    173             a = self.stack.pop()
    174             b = self.stack.pop()
    175             if isinstance(a.value, int):
    176                 self.stack.append(Auto(b.value // a.value))
    177             else:
    178                 self.stack.append(Auto(b.value / a.value))
    179         elif t.type == "AND":
    180             a = self.stack.pop()
    181             b = self.stack.pop()
    182             self.stack.append(Auto(b.value and a.value))
    183         elif t.type == "OR":
    184             a = self.stack.pop()
    185             b = self.stack.pop()
    186             self.stack.append(Auto(b.value or a.value))
    187         elif t.type == "NOT":
    188             a = self.stack.pop()
    189             self.stack.append(Auto(not a.value))
    190         elif t.type == "NEG":
    191             a = self.stack.pop()
    192             if isinstance(a.value, str):
    193                 self.stack.append(Auto(a.value[::-1]))
    194             else:
    195                 self.stack.append(Auto(-a.value))
    196         elif t.type == "JUMP_IF_FALSE":
    197             a = self.stack.pop()
    198             if not a.value:
    199                 self.i =  int(t.value)
    200         elif t.type == "JUMP":
    201             self.i = int(t.value)
    202         elif t.type == "PRINT":
    203             print(*self.stack)
    204             self.stack = []
    205         elif t.type == "GET_METHOD":
    206             a = self.stack.pop()
    207             b = self.stack.pop()
    208             c = b.namespace.get(a.value, None)
    209             if c is None:
    210                 c = Auto(None, belongto=b, name=a.value)
    211                 b.namespace[a.value] = c
    212             self.stack.append(c)
    213         elif t.type == "CALL":
    214             args = self.stack[-t.value:] if t.value else []
    215             for x in range(t.value):
    216                 self.stack.pop()
    217             a = self.stack.pop()
    218             self.stack.append(a.call(args, lineno=t.lineno))
    219         elif t.type == "RETURN":
    220             a = self.stack.pop()
    221             self.stack = [a]
    222             self.i = self.l
    223         elif t.type == "MAKE_FUNCTION":
    224             a = self.stack.pop()
    225             b = self.stack.pop()
    226             if isinstance(b.value, list) and isinstance(a.value, list):
    227                 self.stack.append(Auto("<function>", argnames=a.value, belongto=self, code=b.value or []))
    228             else:
    229                 self.stack.append(Auto(None))
    230         elif t.type == 'BUILD_LIST':
    231             l = self.stack[-t.value:] if t.value else []
    232             for x in range(t.value):
    233                 self.stack.pop()
    234             self.stack.append(Auto(l))
    235         elif t.type == 'BUILD_MAP':
    236             m = {}
    237             for x in range(t.value):
    238                 v = self.stack.pop()
    239                 i = self.stack.pop()
    240                 m[i.value] = v
    241             self.stack.append(Auto(m))
    242         elif t.type == 'GET_ITEM':
    243             a = self.stack.pop()
    244             b = self.stack.pop()
    245             if isinstance(a.value, int) and isinstance(b.value, list):
    246                 if a.value < len(b.value):
    247                     c = b.value[a.value]
    248                 else:
    249                     for x in range(len(b.value), a.value+1):
    250                         b.value.append(Auto())
    251                     c = b.value[-1]
    252             elif isinstance(a.value, int) and isinstance(b.value, str):
    253                 if a.value < len(b.value):
    254                     c = Auto(b.value[a.value])
    255                 else:
    256                     c = Auto()
    257             elif isinstance(a.value, str) and isinstance(b.value, dict):
    258                 c = b.value.get(a.value,None)
    259                 if c is None:
    260                     c = Auto()
    261                     b.value[a.value] = c
    262             else:
    263                 raise PymRunError("error in getitem"+"(第{0}行)".format(t.lineno))
    264             c.belongto = b
    265             self.stack.append(c)
    266         else:
    267             raise PymRunError('canot run '+t.type+"(第{0}行)".format(t.lineno))
    268         if show_var:
    269             print(" "*40,self.stack)
    270             print(" "*40,self.namespace)
    271 
    272     def func_register(self, name, func):
    273         self.namespace[name] = Auto("<buildin-function "+name+'>',
    274                                     buildin=func, name=name, belongto=self)
    275 
    276     def method_register(self, father, name, func):
    277         father_auto = self.namespace[father]
    278         if father_auto:
    279             father_auto.namespace[name] = Auto("<buildin-function "+name+'>',
    280                                     buildin=func, name=name, belongto=father_auto)
    281 
    282     def multi_register(self, func, *names):
    283         if len(names) == 1:
    284             self.func_register(names[0], func)
    285         elif len(names) == 2:
    286             self.method_register(names[0], names[1], func)
    287 
    288 
    289 # 使用装饰器pym_warpper自定义内置函数
    290 # 内置函数在python中有且仅有一个参数args
    291 # args是个数组,其中包含了pym中传过来的Auto变量
    292 # 函数需要返回一个Auto变量
    293 # 最后内置函数用func_register或method_register挂到pym运行环境里
    294 
    295 @pym_warpper("str")
    296 def function_str(args):
    297     return Auto(str(args[0])) if args else Auto()
    298 
    299 @pym_warpper("int")
    300 def function_int(args):
    301     return Auto(it(args[0])) if args else Auto()
    302 
    303 @pym_warpper("len")
    304 def function_len(args):
    305     return Auto(len(args[0].value)) if args else Auto()
    306 
    307 @pym_warpper("format")
    308 def function_format(args):
    309     return Auto(args[0].value.format(*args[1:])) if len(args)>=2 else Auto()
    310 
    311 
    312 @pym_warpper("require")
    313 def function_require(args):
    314     if not args:
    315         return Auto()
    316     path = args[0].value
    317     if not path or not isinstance(path, str):
    318         return Auto()
    319     return Auto()
    320 
    321 @pym_warpper("exec")
    322 def function_exec(args):
    323     if len(args) != 2:
    324         return Auto()
    325     # if not isinstance(args[1].value, str):
    326     #     raise PymRunError("buildin-function exec need a argument(str)")
    327     # print(type(args[0].value), args[0].value)
    328     # print("comp", auto.get_name(), args[1].get_name())
    329     PymRuntime(args[0], with_buildin=False).exec(args[1].value, args[0].get_name())
    330     return Auto()
    331 
    332 #
    333 # @pym_warpper("std")
    334 # def function_standard(args):
    335 #     return Auto()
    336 # @pym_warpper("std", "pow")
    337 # def method_standard_pow(args):
    338 #     return Auto(args[0].value**args[1].value) if len(args)>=2 else Auto()
    339 
    340 class PymRuntime:
    341     def __init__(self, base=None, with_buildin=True):
    342         if not base:
    343             base = Auto(code=[], name='__main__')
    344         if with_buildin:
    345             for names, func in Ready_Registers:
    346                 base.multi_register(func, *names)
    347             base.call()
    348         self.run_time = base
    349 
    350     def exec(self, code, filename = ""):
    351         filename = ("("+filename+")") if filename else ""
    352         try:
    353             tokens = tokenize(code)
    354             stepstmp = stepize(tokens)
    355             if show_tokens:
    356                 print("
    [TOKENIZE "+filename+"]")
    357                 print("
    ".join([str(t) for t in tokens]))
    358             if show_steps:
    359                 print("
    [STEPIZE "+filename+"]")
    360                 for i, x in enumerate(stepstmp):
    361                     print(" {0:3}".format(i), x)
    362 
    363             # 函数运行时的压栈(为了实现嵌套调用exec)
    364             last_code = self.run_time.code
    365             last_i = self.run_time.i
    366             last_l = self.run_time.l
    367 
    368             # 函数执行
    369             self.run_time.code = stepstmp or []
    370             self.run_time.call()
    371 
    372             # 函数执行完毕,返回上一层
    373             self.run_time.code = last_code
    374             self.run_time.i = last_i
    375             self.run_time.l = last_l
    376         except PymTokenizeError as e:
    377             print("[PymTokenizeError]", e, filename)
    378         except PymStepizeError as e:
    379             print("[PymStepizeError]", e, filename)
    380         except PymRunError as e:
    381             print("[PymRunError]", e, filename)
    382         # finally:
    383         #     raise Exception
    384         # except Exception as e:
    385         #     print("[PythonError]", e, filename)
    386 
    387 
    388 if __name__ == '__main__':
    389     pym = PymRuntime()
    390     pym.exec(open("hello.pym", encoding='utf-8').read(), filename="hello.pym")
    391     # PymRuntime(pym.run_time).exec("a = 1; a += 1; print a;", filename="hello.pym")
    392     # pym.exec("a += 1; print a;", filename="hello.pym")
    393     # pym.exec("")
    394     # pym.exec('a = 1; a += 1; print "ad
    s";')
    pym.py

    另外,做了一个repl服务器:

    总之挺帅的。
  • 相关阅读:
    zookeeper的集群搭建
    Java代码操作zookeeper
    zookeeper的简介和相关命令操作
    Linux上搭建zookeeper服务注册中心
    Java8新特性(三)之方法引用和构造器引用
    Java8新特性(一)之Lambda表达式
    react-navigation 3.x版本的使用
    react-navigation 3.x版本的安装以及react-native-gesture-handler配置
    react-native 打包 出apk
    webpack的使用
  • 原文地址:https://www.cnblogs.com/backinfile/p/11529911.html
Copyright © 2011-2022 走看看