} else if (c != '\\') { buf.append((char)c); } lastC = c; }
} } }   if (inOctalCode) buf.append((char)octalCode);
	private ExpressionTreeNode parseFactor(Preprocessor p) throws IOException, MapyrusException	{		boolean parsedDigit;		StringBuffer buf = new StringBuffer();		ExpressionTreeNode expr;		int c, lastC, quote;		c = p.readNonSpace();		if (c == '\'' || c == '"')		{			/*			 * It's a quoted string.  Keep reading up until matching quote.			 */			lastC = quote = c;			while ((c = p.read()) != quote || lastC == '\\')			{				if (c == -1)				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.UNEXPECTED_EOF));				}				if (lastC == '\\')				{					/*					 * '\\' compressed to single backslash,					 * '\n' converted to a newline, '\r' is stripped -- it					 * is not useful since we use Java's line separator internally.					 * Escaping of other characters is ignored.					 */					if (c == 'n')						buf.append(Constants.LINE_SEPARATOR);					else if (c != 'r')						buf.append((char)c);				}				else if (c != '\\')				{					buf.append((char)c);				}				lastC = c;			}			return(new ExpressionTreeNode(new Argument(Argument.STRING, buf.toString())));		}		if (Character.isDigit((char)c) || c == '.')		{			/*			 * Parse a decimal number and return it as a leaf node.			 */			parsedDigit = false;			while (Character.isDigit((char)c))			{				parsedDigit = true;				buf.append((char)c);				c = p.read();			}						if (c == '.')			{				buf.append((char)c);				c = p.read();			}			while (Character.isDigit((char)c))			{				parsedDigit = true;				buf.append((char)c);				c = p.read();			}			if (!parsedDigit)			{				throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +					": " + MapyrusMessages.get(MapyrusMessages.INVALID_NUMBER));			}			if (c == 'e' || c == 'E')			{				buf.append((char)c);				c = p.read();				if (c == '+' || c == '-')				{					buf.append((char)c);					c = p.read();				}				/*				 * Expect at least one digit for the exponent value.				 */				if (!Character.isDigit((char)c))				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.INVALID_NUMBER));				}				while (Character.isDigit((char)c))				{					buf.append((char)c);					c = p.read();				}			}			p.unread(c);			double d = 0.0;			try			{				d = Double.parseDouble(buf.toString());			}			catch (NumberFormatException e)			{				/*				 * We parsed the number so it will				 * always be valid.				 */			}			return(new ExpressionTreeNode(new Argument(d)));		}		if (c == -1)		{			throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +				": " + MapyrusMessages.get(MapyrusMessages.UNEXPECTED_EOF));		}		if (c == '(')		{			expr = parseOrBoolean(p);			c = p.readNonSpace();			if (c != ')')			{				throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +					": " + MapyrusMessages.get(MapyrusMessages.UNMATCHED_BRACKET));			}		}		else if (Character.isLetter((char)c) || c == '$')		{			/*			 * It does not look like a numeric expression or a string			 * expression so maybe it is a variable name or function.			 */			buf.append((char)c);			c = p.read();			while (c != -1 && (c == '.' || c == '_' ||				Character.isLetterOrDigit((char)c)))			{				buf.append((char)c);				c = p.read();			}			/*			 * Is this a function call like "round(3.14)"?			 */			Integer functionType = (Integer)(mFunctionTypeLookup.get(buf.toString()));			if (functionType != null)			{				/*				 * Parse opening '(', arguments for this function, then closing ')'.				 */				if (Character.isWhitespace((char)c))					c = p.readNonSpace();				if (c != '(')				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.EXPECTED) + ": '('");				}				int nArgs = mFunctionArgumentCount[functionType.intValue()];				ExpressionTreeNode functionExpressions[] = new ExpressionTreeNode[Math.max(nArgs, 3)];				/*				 * Parse expression for each function argument.				 */				for (int i = 0; i < functionExpressions.length; i++)					functionExpressions[i] = null;				for (int i = 0; i < nArgs; i++)				{					if (i > 0)					{						/*						 * Parse comma before next value.						 */						c = p.readNonSpace();						if (c != ',')						{							throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +								": " + MapyrusMessages.get(MapyrusMessages.WRONG_FUNCTION_VALUES) +								": " + buf.toString());						}					}					functionExpressions[i] = parseOrBoolean(p);				}				c = p.readNonSpace();				if (c != ')')				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.WRONG_FUNCTION_VALUES) +						": " + buf.toString());				}				expr = new ExpressionTreeNode(functionType.intValue(),					functionExpressions[0], functionExpressions[1], functionExpressions[2]);			}			else			{				p.unread(c);				expr = new ExpressionTreeNode(new Argument(Argument.VARIABLE, buf.toString()));			}			}		else		{			/*			 * It's nothing that we understand.			 */			throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +				": " + MapyrusMessages.get(MapyrusMessages.INVALID_EXPRESSION));		}		return(expr);	}