@SuppressWarnings("unchecked")
	void monitor() throws ScriptException {
		int[] countPlusIndexes = new int[5];
		float[] rangeMinMax = new float[2];
		Token token;
		if (statementLength == 1) {
			viewer.hideMeasurements(false);
			return;
		}
		token = getToken(1);
		switch (statementLength) {
		case 2:
			switch (token.tok) {
			case Token.on:
				viewer.hideMeasurements(false);
				return;
			case Token.off:
				viewer.hideMeasurements(true);
				return;
			case Token.delete:
				viewer.clearAllMeasurements();
				return;
			case Token.string:
				viewer.setMeasurementFormats((String) token.value);
				return;
			default:
				keywordExpected("ON, OFF, or DELETE");
			}
		case 3: // measure delete N
			if (token.tok == Token.delete) {
				if (statement[2].tok == Token.all)
					viewer.clearAllMeasurements();
				else viewer.deleteMeasurement(intParameter(2) - 1);
				return;
			}
		}
		countPlusIndexes[0] = 0;
		int argCount = statementLength - 1;
		int expressionCount = 0;
		int atomIndex = -1;
		int atomNumber = 0;
		int ptFloat = -1;
		rangeMinMax[0] = Float.MAX_VALUE;
		rangeMinMax[1] = Float.MAX_VALUE;
		boolean isAll = false;
		boolean isAllConnected = false;
		boolean isExpression = false;
		boolean isDelete = false;
		boolean isRange = true;
		boolean isON = false;
		boolean isOFF = false;
		String strFormat = null;
		Vector monitorExpressions = new Vector();

		BitSet bs = new BitSet();

		for (int i = 1; i <= argCount; ++i) {
			token = getToken(i);
			switch (token.tok) {
			case Token.on:
				if (isON || isOFF || isDelete)
					invalidArgument();
				isON = true;
				continue;
			case Token.off:
				if (isON || isOFF || isDelete)
					invalidArgument();
				isOFF = true;
				continue;
			case Token.delete:
				if (isON || isOFF || isDelete)
					invalidArgument();
				isDelete = true;
				continue;
			case Token.range:
				isRange = true; // unnecessary
				atomIndex = -1;
				isAll = true;
				continue;
			case Token.identifier:
				if (((String) token.value).equalsIgnoreCase("ALLCONNECTED"))
					isAllConnected = true;
				else keywordExpected("ALL, ALLCONNECTED, or DELETE");
				// fall through
			case Token.all:
				atomIndex = -1;
				isAll = true;
				continue;
			case Token.string:
				// measures "%a1 %a2 %v %u"
				strFormat = (String) token.value;
				continue;
			case Token.decimal:
				isAll = true;
				isRange = true;
				ptFloat = (ptFloat + 1) % 2;
				rangeMinMax[ptFloat] = ((Float) token.value).floatValue();
				continue;
			case Token.integer:
				isRange = true; // irrelevant if just four integers
				atomNumber = token.intValue;
				atomIndex = viewer.getAtomIndexFromAtomNumber(atomNumber);
				ptFloat = (ptFloat + 1) % 2;
				rangeMinMax[ptFloat] = atomNumber;
				break;
			case Token.expressionBegin:
				isExpression = true;
				bs = expression(statement, i);
				atomIndex = viewer.firstAtomOf(bs);
				i = pcLastExpressionInstruction;
				break;
			default:
				expressionOrIntegerExpected();
			}
			// only here for point definition
			if (atomIndex == -1)
				badAtomNumber();
			if (isAll) {
				if (bs == null || bs.size() == 0)
					badAtomNumber();
				if (++expressionCount > 4)
					badArgumentCount();
				monitorExpressions.add(bs);
			}
			else {
				if (++countPlusIndexes[0] > 4)
					badArgumentCount();
				countPlusIndexes[countPlusIndexes[0]] = atomIndex;
			}
		}
		if (isAll) {
			if (!isExpression)
				expressionExpected();
			if (isRange && rangeMinMax[1] < rangeMinMax[0]) {
				rangeMinMax[1] = rangeMinMax[0];
				rangeMinMax[0] = (rangeMinMax[1] == Float.MAX_VALUE ? Float.MAX_VALUE : -200F);
			}
			viewer.defineMeasurement(monitorExpressions, rangeMinMax, isDelete, isAllConnected, isON || isOFF, isOFF,
					strFormat);
		}
		else if (isDelete)
			viewer.deleteMeasurement(countPlusIndexes);
		else if (isON)
			viewer.showMeasurement(countPlusIndexes, true);
		else if (isOFF)
			viewer.showMeasurement(countPlusIndexes, false);
		else viewer.toggleMeasurement(countPlusIndexes, strFormat);
	}