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服务器:

    总之挺帅的。
  • 相关阅读:
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 735 行星碰撞(栈)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Java实现 蓝桥杯算法提高 求最大值
    Python eval() 函数
    Python repr() 函数
  • 原文地址:https://www.cnblogs.com/backinfile/p/11529911.html
Copyright © 2011-2022 走看看