basparse.py

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

PY
425
字号
# An implementation of Dartmouth BASIC (1964)#from ply import *import basiclextokens = basiclex.tokensprecedence = (               ('left', 'PLUS','MINUS'),               ('left', 'TIMES','DIVIDE'),               ('left', 'POWER'),               ('right','UMINUS'))#### A BASIC program is a series of statements.  We represent the program as a#### dictionary of tuples indexed by line number.def p_program(p):    '''program : program statement               | statement'''    if len(p) == 2 and p[1]:       p[0] = { }       line,stat = p[1]       p[0][line] = stat    elif len(p) ==3:       p[0] = p[1]       if not p[0]: p[0] = { }       if p[2]:           line,stat = p[2]           p[0][line] = stat#### This catch-all rule is used for any catastrophic errors.  In this case,#### we simply return nothingdef p_program_error(p):    '''program : error'''    p[0] = None    p.parser.error = 1#### Format of all BASIC statements.def p_statement(p):    '''statement : INTEGER command NEWLINE'''    if isinstance(p[2],str):        print p[2],"AT LINE", p[1]        p[0] = None        p.parser.error = 1    else:        lineno = int(p[1])        p[0] = (lineno,p[2])#### Interactive statements.def p_statement_interactive(p):    '''statement : RUN NEWLINE                 | LIST NEWLINE                 | NEW NEWLINE'''    p[0] = (0, (p[1],0))#### Blank line numberdef p_statement_blank(p):    '''statement : INTEGER NEWLINE'''    p[0] = (0,('BLANK',int(p[1])))#### Error handling for malformed statementsdef p_statement_bad(p):    '''statement : INTEGER error NEWLINE'''    print "MALFORMED STATEMENT AT LINE", p[1]    p[0] = None    p.parser.error = 1#### Blank linedef p_statement_newline(p):    '''statement : NEWLINE'''    p[0] = None#### LET statementdef p_command_let(p):    '''command : LET variable EQUALS expr'''    p[0] = ('LET',p[2],p[4])def p_command_let_bad(p):    '''command : LET variable EQUALS error'''    p[0] = "BAD EXPRESSION IN LET"#### READ statementdef p_command_read(p):    '''command : READ varlist'''    p[0] = ('READ',p[2])def p_command_read_bad(p):    '''command : READ error'''    p[0] = "MALFORMED VARIABLE LIST IN READ"#### DATA statementdef p_command_data(p):    '''command : DATA numlist'''    p[0] = ('DATA',p[2])def p_command_data_bad(p):    '''command : DATA error'''    p[0] = "MALFORMED NUMBER LIST IN DATA"#### PRINT statementdef p_command_print(p):    '''command : PRINT plist optend'''    p[0] = ('PRINT',p[2],p[3])def p_command_print_bad(p):    '''command : PRINT error'''    p[0] = "MALFORMED PRINT STATEMENT"#### Optional ending on PRINT. Either a comma (,) or semicolon (;)def p_optend(p):    '''optend : COMMA              | SEMI              |'''    if len(p)  == 2:         p[0] = p[1]    else:         p[0] = None#### PRINT statement with no argumentsdef p_command_print_empty(p):    '''command : PRINT'''    p[0] = ('PRINT',[],None)#### GOTO statementdef p_command_goto(p):    '''command : GOTO INTEGER'''    p[0] = ('GOTO',int(p[2]))def p_command_goto_bad(p):    '''command : GOTO error'''    p[0] = "INVALID LINE NUMBER IN GOTO"#### IF-THEN statementdef p_command_if(p):    '''command : IF relexpr THEN INTEGER'''    p[0] = ('IF',p[2],int(p[4]))def p_command_if_bad(p):    '''command : IF error THEN INTEGER'''    p[0] = "BAD RELATIONAL EXPRESSION"def p_command_if_bad2(p):    '''command : IF relexpr THEN error'''    p[0] = "INVALID LINE NUMBER IN THEN"#### FOR statementdef p_command_for(p):    '''command : FOR ID EQUALS expr TO expr optstep'''    p[0] = ('FOR',p[2],p[4],p[6],p[7])def p_command_for_bad_initial(p):    '''command : FOR ID EQUALS error TO expr optstep'''    p[0] = "BAD INITIAL VALUE IN FOR STATEMENT"def p_command_for_bad_final(p):    '''command : FOR ID EQUALS expr TO error optstep'''    p[0] = "BAD FINAL VALUE IN FOR STATEMENT"def p_command_for_bad_step(p):    '''command : FOR ID EQUALS expr TO expr STEP error'''    p[0] = "MALFORMED STEP IN FOR STATEMENT"#### Optional STEP qualifier on FOR statementdef p_optstep(p):    '''optstep : STEP expr               | empty'''    if len(p) == 3:       p[0] = p[2]    else:       p[0] = None#### NEXT statementdef p_command_next(p):    '''command : NEXT ID'''    p[0] = ('NEXT',p[2])def p_command_next_bad(p):    '''command : NEXT error'''    p[0] = "MALFORMED NEXT"#### END statementdef p_command_end(p):    '''command : END'''    p[0] = ('END',)#### REM statementdef p_command_rem(p):    '''command : REM'''    p[0] = ('REM',p[1])#### STOP statementdef p_command_stop(p):    '''command : STOP'''    p[0] = ('STOP',)#### DEF statementdef p_command_def(p):    '''command : DEF ID LPAREN ID RPAREN EQUALS expr'''    p[0] = ('FUNC',p[2],p[4],p[7])def p_command_def_bad_rhs(p):    '''command : DEF ID LPAREN ID RPAREN EQUALS error'''    p[0] = "BAD EXPRESSION IN DEF STATEMENT"def p_command_def_bad_arg(p):    '''command : DEF ID LPAREN error RPAREN EQUALS expr'''    p[0] = "BAD ARGUMENT IN DEF STATEMENT"#### GOSUB statementdef p_command_gosub(p):    '''command : GOSUB INTEGER'''    p[0] = ('GOSUB',int(p[2]))def p_command_gosub_bad(p):    '''command : GOSUB error'''    p[0] = "INVALID LINE NUMBER IN GOSUB"#### RETURN statementdef p_command_return(p):    '''command : RETURN'''    p[0] = ('RETURN',)#### DIM statementdef p_command_dim(p):    '''command : DIM dimlist'''    p[0] = ('DIM',p[2])def p_command_dim_bad(p):    '''command : DIM error'''    p[0] = "MALFORMED VARIABLE LIST IN DIM"#### List of variables supplied to DIM statementdef p_dimlist(p):    '''dimlist : dimlist COMMA dimitem               | dimitem'''    if len(p) == 4:        p[0] = p[1]        p[0].append(p[3])    else:        p[0] = [p[1]]#### DIM itemsdef p_dimitem_single(p):    '''dimitem : ID LPAREN INTEGER RPAREN'''    p[0] = (p[1],eval(p[3]),0)def p_dimitem_double(p):    '''dimitem : ID LPAREN INTEGER COMMA INTEGER RPAREN'''    p[0] = (p[1],eval(p[3]),eval(p[5]))#### Arithmetic expressionsdef p_expr_binary(p):    '''expr : expr PLUS expr            | expr MINUS expr            | expr TIMES expr            | expr DIVIDE expr            | expr POWER expr'''    p[0] = ('BINOP',p[2],p[1],p[3])def p_expr_number(p):    '''expr : INTEGER            | FLOAT'''    p[0] = ('NUM',eval(p[1]))def p_expr_variable(p):    '''expr : variable'''    p[0] = ('VAR',p[1])def p_expr_group(p):    '''expr : LPAREN expr RPAREN'''    p[0] = ('GROUP',p[2])def p_expr_unary(p):    '''expr : MINUS expr %prec UMINUS'''    p[0] = ('UNARY','-',p[2])#### Relational expressionsdef p_relexpr(p):    '''relexpr : expr LT expr               | expr LE expr               | expr GT expr               | expr GE expr               | expr EQUALS expr               | expr NE expr'''    p[0] = ('RELOP',p[2],p[1],p[3])#### Variablesdef p_variable(p):    '''variable : ID              | ID LPAREN expr RPAREN              | ID LPAREN expr COMMA expr RPAREN'''    if len(p) == 2:       p[0] = (p[1],None,None)    elif len(p) == 5:       p[0] = (p[1],p[3],None)    else:       p[0] = (p[1],p[3],p[5])#### Builds a list of variable targets as a Python listdef p_varlist(p):    '''varlist : varlist COMMA variable               | variable'''    if len(p) > 2:       p[0] = p[1]       p[0].append(p[3])    else:       p[0] = [p[1]]#### Builds a list of numbers as a Python listdef p_numlist(p):    '''numlist : numlist COMMA number               | number'''    if len(p) > 2:       p[0] = p[1]       p[0].append(p[3])    else:       p[0] = [p[1]]#### A number. May be an integer or a floatdef p_number(p):    '''number  : INTEGER               | FLOAT'''    p[0] = eval(p[1])#### A signed number.def p_number_signed(p):    '''number  : MINUS INTEGER               | MINUS FLOAT'''    p[0] = eval("-"+p[2])#### List of targets for a print statement#### Returns a list of tuples (label,expr)def p_plist(p):    '''plist   : plist COMMA pitem               | pitem'''    if len(p) > 3:       p[0] = p[1]       p[0].append(p[3])    else:       p[0] = [p[1]]def p_item_string(p):    '''pitem : STRING'''    p[0] = (p[1][1:-1],None)def p_item_string_expr(p):    '''pitem : STRING expr'''    p[0] = (p[1][1:-1],p[2])def p_item_expr(p):    '''pitem : expr'''    p[0] = ("",p[1])#### Emptydef p_empty(p):    '''empty : '''#### Catastrophic error handlerdef p_error(p):    if not p:        print "SYNTAX ERROR AT EOF"bparser = yacc.yacc()def parse(data):    bparser.error = 0    p = bparser.parse(data)    if bparser.error: return None    return p

⌨️ 快捷键说明

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