gardensnake.py

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· Python 代码 · 共 710 行 · 第 1/2 页

PY
710
字号
# The grammar comments come from Python's Grammar/Grammar file## NB: compound_stmt in single_input is followed by extra NEWLINE!# file_input: (NEWLINE | stmt)* ENDMARKERdef p_file_input_end(p):    """file_input_end : file_input ENDMARKER"""    p[0] = ast.Stmt(p[1])def p_file_input(p):    """file_input : file_input NEWLINE                  | file_input stmt                  | NEWLINE                  | stmt"""    if isinstance(p[len(p)-1], basestring):        if len(p) == 3:            p[0] = p[1]        else:            p[0] = [] # p == 2 --> only a blank line    else:        if len(p) == 3:            p[0] = p[1] + p[2]        else:            p[0] = p[1]# funcdef: [decorators] 'def' NAME parameters ':' suite# ignoring decoratorsdef p_funcdef(p):    "funcdef : DEF NAME parameters COLON suite"    p[0] = ast.Function(None, p[2], tuple(p[3]), (), 0, None, p[5])# parameters: '(' [varargslist] ')'def p_parameters(p):    """parameters : LPAR RPAR                  | LPAR varargslist RPAR"""    if len(p) == 3:        p[0] = []    else:        p[0] = p[2]# varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) |# highly simplifieddef p_varargslist(p):    """varargslist : varargslist COMMA NAME                   | NAME"""    if len(p) == 4:        p[0] = p[1] + p[3]    else:        p[0] = [p[1]]# stmt: simple_stmt | compound_stmtdef p_stmt_simple(p):    """stmt : simple_stmt"""    # simple_stmt is a list    p[0] = p[1]def p_stmt_compound(p):    """stmt : compound_stmt"""    p[0] = [p[1]]# simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINEdef p_simple_stmt(p):    """simple_stmt : small_stmts NEWLINE                   | small_stmts SEMICOLON NEWLINE"""    p[0] = p[1]def p_small_stmts(p):    """small_stmts : small_stmts SEMICOLON small_stmt                   | small_stmt"""    if len(p) == 4:        p[0] = p[1] + [p[3]]    else:        p[0] = [p[1]]# small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |#    import_stmt | global_stmt | exec_stmt | assert_stmtdef p_small_stmt(p):    """small_stmt : flow_stmt                  | expr_stmt"""    p[0] = p[1]# expr_stmt: testlist (augassign (yield_expr|testlist) |#                      ('=' (yield_expr|testlist))*)# augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |#             '<<=' | '>>=' | '**=' | '//=')def p_expr_stmt(p):    """expr_stmt : testlist ASSIGN testlist                 | testlist """    if len(p) == 2:        # a list of expressions        p[0] = ast.Discard(p[1])    else:        p[0] = Assign(p[1], p[3])def p_flow_stmt(p):    "flow_stmt : return_stmt"    p[0] = p[1]# return_stmt: 'return' [testlist]def p_return_stmt(p):    "return_stmt : RETURN testlist"    p[0] = ast.Return(p[2])def p_compound_stmt(p):    """compound_stmt : if_stmt                     | funcdef"""    p[0] = p[1]def p_if_stmt(p):    'if_stmt : IF test COLON suite'    p[0] = ast.If([(p[2], p[4])], None)def p_suite(p):    """suite : simple_stmt             | NEWLINE INDENT stmts DEDENT"""    if len(p) == 2:        p[0] = ast.Stmt(p[1])    else:        p[0] = ast.Stmt(p[3])def p_stmts(p):    """stmts : stmts stmt             | stmt"""    if len(p) == 3:        p[0] = p[1] + p[2]    else:        p[0] = p[1]## No using Python's approach because Ply supports precedence# comparison: expr (comp_op expr)*# arith_expr: term (('+'|'-') term)*# term: factor (('*'|'/'|'%'|'//') factor)*# factor: ('+'|'-'|'~') factor | power# comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'def make_lt_compare((left, right)):    return ast.Compare(left, [('<', right),])def make_gt_compare((left, right)):    return ast.Compare(left, [('>', right),])def make_eq_compare((left, right)):    return ast.Compare(left, [('==', right),])binary_ops = {    "+": ast.Add,    "-": ast.Sub,    "*": ast.Mul,    "/": ast.Div,    "<": make_lt_compare,    ">": make_gt_compare,    "==": make_eq_compare,}unary_ops = {    "+": ast.UnaryAdd,    "-": ast.UnarySub,    }precedence = (    ("left", "EQ", "GT", "LT"),    ("left", "PLUS", "MINUS"),    ("left", "MULT", "DIV"),    )def p_comparison(p):    """comparison : comparison PLUS comparison                  | comparison MINUS comparison                  | comparison MULT comparison                  | comparison DIV comparison                  | comparison LT comparison                  | comparison EQ comparison                  | comparison GT comparison                  | PLUS comparison                  | MINUS comparison                  | power"""    if len(p) == 4:        p[0] = binary_ops[p[2]]((p[1], p[3]))    elif len(p) == 3:        p[0] = unary_ops[p[1]](p[2])    else:        p[0] = p[1]# power: atom trailer* ['**' factor]# trailers enables function calls.  I only allow one level of calls# so this is 'trailer'def p_power(p):    """power : atom             | atom trailer"""    if len(p) == 2:        p[0] = p[1]    else:        if p[2][0] == "CALL":            p[0] = ast.CallFunc(p[1], p[2][1], None, None)        else:            raise AssertionError("not implemented")def p_atom_name(p):    """atom : NAME"""    p[0] = ast.Name(p[1])def p_atom_number(p):    """atom : NUMBER            | STRING"""    p[0] = ast.Const(p[1])def p_atom_tuple(p):    """atom : LPAR testlist RPAR"""    p[0] = p[2]# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAMEdef p_trailer(p):    "trailer : LPAR arglist RPAR"    p[0] = ("CALL", p[2])# testlist: test (',' test)* [',']# Contains shift/reduce errordef p_testlist(p):    """testlist : testlist_multi COMMA                | testlist_multi """    if len(p) == 2:        p[0] = p[1]    else:        # May need to promote singleton to tuple        if isinstance(p[1], list):            p[0] = p[1]        else:            p[0] = [p[1]]    # Convert into a tuple?    if isinstance(p[0], list):        p[0] = ast.Tuple(p[0])def p_testlist_multi(p):    """testlist_multi : testlist_multi COMMA test                      | test"""    if len(p) == 2:        # singleton        p[0] = p[1]    else:        if isinstance(p[1], list):            p[0] = p[1] + [p[3]]        else:            # singleton -> tuple            p[0] = [p[1], p[3]]# test: or_test ['if' or_test 'else' test] | lambdef#  as I don't support 'and', 'or', and 'not' this works down to 'comparison'def p_test(p):    "test : comparison"    p[0] = p[1]# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)# XXX INCOMPLETE: this doesn't allow the trailing commadef p_arglist(p):    """arglist : arglist COMMA argument               | argument"""    if len(p) == 4:        p[0] = p[1] + [p[3]]    else:        p[0] = [p[1]]# argument: test [gen_for] | test '=' test  # Really [keyword '='] testdef p_argument(p):    "argument : test"    p[0] = p[1]def p_error(p):    #print "Error!", repr(p)    raise SyntaxError(p)class GardenSnakeParser(object):    def __init__(self, lexer = None):        if lexer is None:            lexer = IndentLexer()        self.lexer = lexer        self.parser = yacc.yacc(start="file_input_end")    def parse(self, code):        self.lexer.input(code)        result = self.parser.parse(lexer = self.lexer)        return ast.Module(None, result)###### Code generation ######from compiler import misc, syntax, pycodegenclass GardenSnakeCompiler(object):    def __init__(self):        self.parser = GardenSnakeParser()    def compile(self, code, filename="<string>"):        tree = self.parser.parse(code)        #print  tree        misc.set_filename(filename, tree)        syntax.check(tree)        gen = pycodegen.ModuleCodeGenerator(tree)        code = gen.getCode()        return code####### Test code #######compile = GardenSnakeCompiler().compilecode = r"""print('LET\'S TRY THIS \\OUT')#Comment heredef x(a):    print('called with',a)    if a == 1:        return 2    if a*2 > 10: return 999 / 4        # Another comment here    return a+2*3ints = (1, 2,   3, 4,5)print('mutiline-expression', ints)t = 4+1/3*2+6*(9-5+1)print('predence test; should be 34+2/3:', t, t==(34+2/3))print('numbers', 1,2,3,4,5)if 1: 8 a=9 print(x(a))print(x(1))print(x(2))print(x(8),'3')print('this is decimal', 1/5)print('BIG DECIMAL', 1.234567891234567e12345)"""# Set up the GardenSnake run-time environmentdef print_(*args):    print "-->", " ".join(map(str,args))globals()["print"] = print_compiled_code = compile(code)exec compiled_code in globals()print "Done"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?