# assignment precedence and right associativity a = b + c * d; a = b = c; a += b *= c; ==> Program( ExpressionStatement(AssignmentExpression( Identifier, AssignOp, BinaryExpression(Identifier, ArithOp, BinaryExpression(Identifier, ArithOp, Identifier)))), ExpressionStatement(AssignmentExpression( Identifier, AssignOp, AssignmentExpression(Identifier, AssignOp, Identifier))), ExpressionStatement(AssignmentExpression( Identifier, AssignOp, AssignmentExpression(Identifier, AssignOp, Identifier)))) # parenthesized assignment targets (a) = b; ((a)) += b; (a.b) = c; (a[b]) = c; ==> Program( ExpressionStatement(AssignmentExpression( ParenthesizedExpression(Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ParenthesizedExpression(ParenthesizedExpression(Identifier)), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ParenthesizedExpression(FieldAccess(Identifier, Identifier)), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ParenthesizedExpression(ArrayAccess(Identifier, Identifier)), AssignOp, Identifier))) # field and array targets with parenthesized receivers (a).b = c; (a)[b] = c; (a = b).c = d; (a = b)[c] = d; ==> Program( ExpressionStatement(AssignmentExpression( FieldAccess(ParenthesizedExpression(Identifier), Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ArrayAccess(ParenthesizedExpression(Identifier), Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( FieldAccess(ParenthesizedExpression( AssignmentExpression(Identifier, AssignOp, Identifier)), Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ArrayAccess(ParenthesizedExpression( AssignmentExpression(Identifier, AssignOp, Identifier)), Identifier), AssignOp, Identifier))) # parenthesized operands in initializers int c = a + (b = 3); int d = (a) + b; int e = ((a + b)); ==> Program( LocalVariableDeclaration(PrimitiveType, VariableDeclarator( Definition, AssignOp, BinaryExpression(Identifier, ArithOp, ParenthesizedExpression(AssignmentExpression( Identifier, AssignOp, IntegerLiteral))))), LocalVariableDeclaration(PrimitiveType, VariableDeclarator( Definition, AssignOp, BinaryExpression(ParenthesizedExpression(Identifier), ArithOp, Identifier))), LocalVariableDeclaration(PrimitiveType, VariableDeclarator( Definition, AssignOp, ParenthesizedExpression(ParenthesizedExpression( BinaryExpression(Identifier, ArithOp, Identifier)))))) # assignments in full expression contexts set(a = b); a[b = c] = d; ==> Program( ExpressionStatement(MethodInvocation(MethodName(Identifier), ArgumentList(AssignmentExpression(Identifier, AssignOp, Identifier)))), ExpressionStatement(AssignmentExpression( ArrayAccess(Identifier, AssignmentExpression(Identifier, AssignOp, Identifier)), AssignOp, Identifier))) # assignments in conditional operands x = cond ? a = b : c; x = cond ? a : (b = c); ==> Program( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, TernaryExpression(Identifier, LogicOp, AssignmentExpression(Identifier, AssignOp, Identifier), Identifier))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, TernaryExpression(Identifier, LogicOp, Identifier, ParenthesizedExpression(AssignmentExpression( Identifier, AssignOp, Identifier)))))) # lambdas in conditional and cast expressions f = cond ? x -> x : y -> y; f = (Function) x -> x; ==> Program( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, TernaryExpression(Identifier, LogicOp, LambdaExpression(Definition, Identifier), LambdaExpression(Definition, Identifier)))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, CastExpression(TypeName, LambdaExpression(Definition, Identifier))))) # parenthesized assignments in unary operands x = (int) -(a = b); x = -(a = b); x = (a)++; ==> Program( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, CastExpression(PrimitiveType, UnaryExpression(ArithOp, ParenthesizedExpression( AssignmentExpression(Identifier, AssignOp, Identifier)))))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, UnaryExpression(ArithOp, ParenthesizedExpression( AssignmentExpression(Identifier, AssignOp, Identifier))))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, UpdateExpression(ParenthesizedExpression(Identifier), UpdateOp)))) # tolerant binary assignment left operands a + b = 3; int c = a + b = 3; a + b += c * d; ==> Program( ExpressionStatement(AssignmentExpression( BinaryExpression(Identifier, ArithOp, Identifier), AssignOp, IntegerLiteral)), LocalVariableDeclaration(PrimitiveType, VariableDeclarator( Definition, AssignOp, AssignmentExpression( BinaryExpression(Identifier, ArithOp, Identifier), AssignOp, IntegerLiteral))), ExpressionStatement(AssignmentExpression( BinaryExpression(Identifier, ArithOp, Identifier), AssignOp, BinaryExpression(Identifier, ArithOp, Identifier)))) # tolerant unary cast and update assignment left operands -a = b; (int) a = b; a++ = b; ==> Program( ExpressionStatement(AssignmentExpression( UnaryExpression(ArithOp, Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( CastExpression(PrimitiveType, Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( UpdateExpression(Identifier, UpdateOp), AssignOp, Identifier))) # tolerant conditional parenthesized and call assignment left operands cond ? a : b = c; (a + b) = c; call() = b; ==> Program( ExpressionStatement(AssignmentExpression( TernaryExpression(Identifier, LogicOp, Identifier, Identifier), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( ParenthesizedExpression(BinaryExpression(Identifier, ArithOp, Identifier)), AssignOp, Identifier)), ExpressionStatement(AssignmentExpression( MethodInvocation(MethodName(Identifier), ArgumentList), AssignOp, Identifier))) # assignments in lambda bodies f = x -> x = y; f = () -> a = b; f = cond ? x -> x = y : z -> z = y; ==> Program( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, LambdaExpression(Definition, AssignmentExpression(Identifier, AssignOp, Identifier)))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, LambdaExpression(FormalParameters, AssignmentExpression(Identifier, AssignOp, Identifier)))), ExpressionStatement(AssignmentExpression(Identifier, AssignOp, TernaryExpression(Identifier, LogicOp, LambdaExpression(Definition, AssignmentExpression(Identifier, AssignOp, Identifier)), LambdaExpression(Definition, AssignmentExpression(Identifier, AssignOp, Identifier)))))) # recover an incomplete binary assignment inside a method class C { void m() { a + b = ; } } ==> Program(ClassDeclaration(class, Definition, ClassBody( MethodDeclaration(void, Definition, FormalParameters, Block( ExpressionStatement(AssignmentExpression( BinaryExpression(Identifier, ArithOp, Identifier), AssignOp, ⚠))))))) # recover an incomplete parenthesized assignment inside a method class C { void m() { (a) = ; } } ==> Program(ClassDeclaration(class, Definition, ClassBody( MethodDeclaration(void, Definition, FormalParameters, Block( ExpressionStatement(AssignmentExpression( ParenthesizedExpression(Identifier), AssignOp, ⚠))))))) # recover an incomplete compound assignment inside a method class C { void m() { a += ; } } ==> Program(ClassDeclaration(class, Definition, ClassBody( MethodDeclaration(void, Definition, FormalParameters, Block( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, ⚠))))))) # recover an incomplete conditional assignment inside a method class C { void m() { x = cond ? y : ; } } ==> Program(ClassDeclaration(class, Definition, ClassBody( MethodDeclaration(void, Definition, FormalParameters, Block( ExpressionStatement(AssignmentExpression(Identifier, AssignOp, TernaryExpression(Identifier, LogicOp, Identifier, ⚠))))))))