private static BufferedImage renderExpression(Expression expr) {
		BufferedImage plus = render("+");
		ArrayList<BufferedImage> terms = new ArrayList<BufferedImage>();
		
		//total up the width of all parts of the expression, and find the height of the tallest one
		int width = 0, height = 0;
		for(int i = 0; i < expr.length(); i++) {
			AlgebraicParticle term = expr.get(i);
			BufferedImage image = render(term);
			
			//if it's an expression that wouldn't have had parentheses around it, add them now
			if(term instanceof Expression && !needsPars(term)) image = parenthesize(image);
			
			terms.add(image);
			
			// Add the width of the term, and if it's positive (and not the first term), add width 
			// of + sign. If it's negative it would already have a - sign
			width += terms.get(i).getWidth();
			if(expr.get(i).sign() && i != 0) width += plus.getWidth();
			
			height = Math.max(height, image.getHeight());
		}
		
		//actually render the expression
		BufferedImage image = image(width, height);
		Graphics2D g = image.createGraphics();
		//keep track how far we've moved horizontally as we render
		int location = 0;
		for(int i = 0; i < expr.length(); i++) {
			AlgebraicParticle term = expr.get(i);
			//if it's positive, render the + sign and add its width to location variable
			if(i != 0  && term.sign()) {
				render(g, image.getHeight(), plus, location);
				location += plus.getWidth();
			}
			//render the term and move location forward its width
			render(g, image.getHeight(), terms.get(i), location);
			location += terms.get(i).getWidth();
		}
		
		return image;
	}