def LeftIncDec(p, w, left, rbp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """ For i++ and i-- """ if word_.ArithId(w) == Id.Arith_DPlus: op_id = Id.Node_PostDPlus elif word_.ArithId(w) == Id.Arith_DMinus: op_id = Id.Node_PostDMinus else: raise AssertionError child = tdop.ToLValue(left) return arith_expr.UnaryAssign(op_id, child)
def LeftIndex(p, w, left, unused_bp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """Array indexing, in both LValue and RValue context. LValue: f[0] = 1 f[x+1] = 2 RValue: a = f[0] b = f[x+1] On RHS, you can have: 1. a = f[0] 2. a = f(x, y)[0] 3. a = f[0][0] # in theory, if we want character indexing? NOTE: a = f[0].charAt() is probably better On LHS, you can only have: 1. a[0] = 1 Nothing else is valid: 2. function calls return COPIES. They need a name, at least in osh. 3. strings don't have mutable characters. """ if not tdop.IsIndexable(left): p_die("The [ operarator doesn't apply to this expression", word=w) index = p.ParseUntil(0) p.Eat(Id.Arith_RBracket) return arith_expr.Binary(word_.ArithId(w), left, index)
def LeftAssign(p, w, left, rbp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """ Normal binary operator like 1+2 or 2*3, etc. """ # x += 1, or a[i] += 1 CheckLhsExpr(left, p.parse_opts.parse_dynamic_arith(), w) return arith_expr.BinaryAssign(word_.ArithId(w), left, p.ParseUntil(rbp))
def NullIncDec(p, w, bp): # type: (TdopParser, word_t, int) -> arith_expr_t """ ++x or ++x[1] """ right = p.ParseUntil(bp) child = tdop.ToLValue(right) if child is None: p_die("This value can't be assigned to", word=w) return arith_expr.UnaryAssign(word_.ArithId(w), child)
def LeftAssign(p, w, left, rbp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """ Normal binary operator like 1+2 or 2*3, etc. """ # x += 1, or a[i] += 1 lhs = ToLValue(left) if lhs is None: # TODO: It would be nice to point at 'left', but osh/word.py doesn't # support arbitrary arith_expr_t. #p_die("Can't assign to this expression", word=w) p_die("Left-hand side of this assignment is invalid", word=w) return arith_expr.BinaryAssign(word_.ArithId(w), lhs, p.ParseUntil(rbp))
def NullPrefixOp(p, w, bp): # type: (TdopParser, word_t, int) -> arith_expr_t """Prefix operator. Low precedence: return, raise, etc. return x+y is return (x+y), not (return x) + y High precedence: logical negation, bitwise complement, etc. !x && y is (!x) && y, not !(x && y) """ right = p.ParseUntil(bp) return arith_expr.Unary(word_.ArithId(w), right)
def LeftIncDec(p, w, left, rbp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """ For i++ and i-- """ arith_id = word_.ArithId(w) if arith_id == Id.Arith_DPlus: op_id = Id.Node_PostDPlus elif arith_id == Id.Arith_DMinus: op_id = Id.Node_PostDMinus else: raise AssertionError() tdop.CheckLhsExpr(left, p.parse_opts.parse_dynamic_arith(), w) return arith_expr.UnaryAssign(op_id, left)
def Next(self): # type: () -> bool self.cur_word = self.w_parser.ReadWord(lex_mode_e.Arith) self.op_id = word_.ArithId(self.cur_word) return True
def LeftBinaryOp(p, w, left, rbp): # type: (TdopParser, word_t, arith_expr_t, int) -> arith_expr_t """ Normal binary operator like 1+2 or 2*3, etc. """ # TODO: w shoudl be a Token, and we should extract the token from it. return arith_expr.Binary(word_.ArithId(w), left, p.ParseUntil(rbp))
def NullIncDec(p, w, bp): # type: (TdopParser, word_t, int) -> arith_expr_t """ ++x or ++x[1] """ right = p.ParseUntil(bp) tdop.CheckLhsExpr(right, p.parse_opts.parse_dynamic_arith(), w) return arith_expr.UnaryAssign(word_.ArithId(w), right)