def p_expr1(p): """expr1 : MINUS expr %prec UMINUS | PLUS expr %prec UMINUS | NEG expr | HANDLE ident | PLUSPLUS ident | MINUSMINUS ident """ p[0] = node.expr(op=p[1], args=node.expr_list([p[2]]))
def p_field_expr(p): """ expr : expr FIELD """ p[0] = node.expr(op=".", args=node.expr_list([p[1], node.ident(name=p[2], lineno=p.lineno(2), lexpos=p.lexpos(2))]))
def p_expr1(p): """expr1 : MINUS expr %prec UMINUS | PLUS expr %prec UMINUS | NEG expr | HANDLE ident | PLUSPLUS ident | MINUSMINUS ident """ p[0] = node.expr(op=p[1],args=node.expr_list([p[2]]))
def p_foo_stmt(p): "foo_stmt : expr OROR expr SEMI" expr1 = p[1][1][0] expr2 = p[3][1][0] ident = expr1.ret args1 = expr1.args args2 = expr2.args p[0] = node.let(ret=ident, args=node.expr("or",node.expr_list([args1,args2])))
def p_foo_stmt(p): "foo_stmt : expr OROR expr SEMI" expr1 = p[1][1][0] expr2 = p[3][1][0] ident = expr1.ret args1 = expr1.args args2 = expr2.args p[0] = node.let(ret=ident, args=node.expr("or", node.expr_list([args1, args2])))
def p_field_expr(p): """ expr : expr FIELD """ p[0] = node.expr(op=".", args=node.expr_list([ p[1], node.ident(name=p[2], lineno=p.lineno(2), lexpos=p.lexpos(2)) ]))
def p_case_list(p): """ case_list : | CASE expr sep stmt_list_opt case_list | CASE expr error stmt_list_opt case_list | OTHERWISE stmt_list """ if len(p) == 1: p[0] = node.stmt_list() elif len(p) == 3: assert isinstance(p[2],node.stmt_list) p[0] = p[2] elif len(p) == 6: p[0] = node.if_stmt(cond_expr=node.expr(op="==", args=node.expr_list([p[2]])), then_stmt=p[4], else_stmt=p[5]) p[0].cond_expr.args.append(None) # None will be replaced using backpatch() else: assert 0
def p_case_list(p): """ case_list : | CASE expr sep stmt_list_opt case_list | CASE expr error stmt_list_opt case_list | OTHERWISE stmt_list """ if len(p) == 1: p[0] = node.stmt_list() elif len(p) == 3: assert isinstance(p[2], node.stmt_list) p[0] = p[2] elif len(p) == 6: p[0] = node.if_stmt(cond_expr=node.expr(op="==", args=node.expr_list([p[2]])), then_stmt=p[4], else_stmt=p[5]) p[0].cond_expr.args.append( None) # None will be replaced using backpatch() else: assert 0
def p_expr2(p): """expr2 : expr AND expr | expr ANDAND expr | expr BACKSLASH expr | expr COLON expr | expr DIV expr | expr DOT expr | expr DOTDIV expr | expr DOTDIVEQ expr | expr DOTEXP expr | expr DOTMUL expr | expr DOTMULEQ expr | expr EQEQ expr | expr EXP expr | expr EXPEQ expr | expr GE expr | expr GT expr | expr LE expr | expr LT expr | expr MINUS expr | expr MUL expr | expr NE expr | expr OR expr | expr OROR expr | expr PLUS expr | expr EQ expr | expr MULEQ expr | expr DIVEQ expr | expr MINUSEQ expr | expr PLUSEQ expr | expr OREQ expr | expr ANDEQ expr """ if p[2] == "=": if p[1].__class__ is node.let: raise NotImplementedError("assignment " "as expression") # The algorithm, which decides if an # expression F(X) # is arrayref or funcall, is implemented in # resolve.py, except the following lines up # to XXX. These lines handle the case where # an undefined array is updated: # >>> clear a # >>> a[1:10]=123 # Though legal in matlab, these lines # confuse the algorithm, which thinks that # the undefined variable is a function name. # To prevent the confusion, we mark these # nodes arrayref as early as during the parse # phase. if p[1].__class__ is node.funcall: # A(B) = C p[1].__class__ = node.arrayref elif p[1].__class__ is node.matrix: # [A1(B1) A2(B2) ...] = C for e in p[1].args: if e.__class__ is node.funcall: e.__class__ = node.arrayref # XXX if isinstance(p[1],node.getfield): #import pdb;pdb.set_trace() # A.B=C setfield(A,B,C) p[0] = node.setfield(p[1].args[0], p[1].args[1], p[3]) else: #assert len(p[1].args) > 0 ret = p[1].args if isinstance(p[1],node.matrix) else p[1] p[0] = node.let(ret=ret, args=p[3], lineno=p.lineno(2), lexpos=p.lexpos(2)) if isinstance(p[1],node.matrix): # TBD: mark idents as "P" - persistent if p[3].__class__ not in (node.ident,node.funcall): #, p[3].__class__ raise NotImplementedError("multi-assignment %d" % p[0].lineno) if p[3].__class__ is node.ident: # [A1(B1) A2(B2) ...] = F implied F() # import pdb; pdb.set_trace() p[3] = node.funcall(func_expr=p[3], args=node.expr_list()) # [A1(B1) A2(B2) ...] = F(X) p[3].nargout = len(p[1].args[0]) elif p[2] == ".*": p[0] = node.dot(p[1],p[3]) elif p[2] == ":" and isinstance(p[1],node.expr) and p[1].op==":": # Colon expression means different things depending on the # context. As an array subscript, it is a slice; otherwise, # it is a call to the "range" function, and the parser can't # tell which is which. So understanding of colon expressions # is put off until after "resolve". p[0] = p[1] p[0].args.insert(1,p[3]) else: p[0] = node.expr(op=p[2],args=node.expr_list([p[1],p[3]]))
def p_paren_expr(p): """ expr : LPAREN expr RPAREN """ p[0] = node.expr(op="parens",args=node.expr_list([p[2]]))
def p_expr_colon(p): "colon : COLON" p[0] = node.expr(op=":",args=node.expr_list())
def p_expr_end(p): "end : END_EXPR" p[0] = node.expr(op="end",args=node.expr_list([node.number(0), node.number(0)]))
def p_expr2(p): """expr2 : expr AND expr | expr ANDAND expr | expr BACKSLASH expr | expr COLON expr | expr DIV expr | expr DOT expr | expr DOTDIV expr | expr DOTDIVEQ expr | expr DOTEXP expr | expr DOTMUL expr | expr DOTMULEQ expr | expr EQEQ expr | expr EXP expr | expr EXPEQ expr | expr GE expr | expr GT expr | expr LE expr | expr LT expr | expr MINUS expr | expr MUL expr | expr NE expr | expr OR expr | expr OROR expr | expr PLUS expr | expr EQ expr | expr MULEQ expr | expr DIVEQ expr | expr MINUSEQ expr | expr PLUSEQ expr | expr OREQ expr | expr ANDEQ expr """ if p[2] == "=": if p[1].__class__ is node.let: raise NotImplementedError("assignment " "as expression") # The algorithm, which decides if an # expression F(X) # is arrayref or funcall, is implemented in # resolve.py, except the following lines up # to XXX. These lines handle the case where # an undefined array is updated: # >>> clear a # >>> a[1:10]=123 # Though legal in matlab, these lines # confuse the algorithm, which thinks that # the undefined variable is a function name. # To prevent the confusion, we mark these # nodes arrayref as early as during the parse # phase. if p[1].__class__ is node.funcall: # A(B) = C p[1].__class__ = node.arrayref elif p[1].__class__ is node.matrix: # [A1(B1) A2(B2) ...] = C for e in p[1].args: if e.__class__ is node.funcall: e.__class__ = node.arrayref # XXX if isinstance(p[1], node.getfield): #import pdb;pdb.set_trace() # A.B=C setfield(A,B,C) p[0] = node.setfield(p[1].args[0], p[1].args[1], p[3]) else: #assert len(p[1].args) > 0 ret = p[1].args if isinstance(p[1], node.matrix) else p[1] p[0] = node.let(ret=ret, args=p[3], lineno=p.lineno(2), lexpos=p.lexpos(2)) if isinstance(p[1], node.matrix): # TBD: mark idents as "P" - persistent if p[3].__class__ not in (node.ident, node.funcall): #, p[3].__class__ raise NotImplementedError("multi-assignment %d" % p[0].lineno) if p[3].__class__ is node.ident: # [A1(B1) A2(B2) ...] = F implied F() # import pdb; pdb.set_trace() p[3] = node.funcall(func_expr=p[3], args=node.expr_list()) # [A1(B1) A2(B2) ...] = F(X) p[3].nargout = len(p[1].args[0]) elif p[2] == ".*": p[0] = node.dot(p[1], p[3]) elif p[2] == ":" and isinstance(p[1], node.expr) and p[1].op == ":": # Colon expression means different things depending on the # context. As an array subscript, it is a slice; otherwise, # it is a call to the "range" function, and the parser can't # tell which is which. So understanding of colon expressions # is put off until after "resolve". p[0] = p[1] p[0].args.insert(1, p[3]) else: p[0] = node.expr(op=p[2], args=node.expr_list([p[1], p[3]]))
def p_paren_expr(p): """ expr : LPAREN expr RPAREN """ p[0] = node.expr(op="parens", args=node.expr_list([p[2]]))
def p_expr_colon(p): "colon : COLON" p[0] = node.expr(op=":", args=node.expr_list())
def p_expr_end(p): "end : END_EXPR" p[0] = node.expr(op="end", args=node.expr_list([node.number(0), node.number(0)]))