if (minArgs >= 0) { ExpressionTreeNode funcExpr = parseOrBoolean(p); functionExpressions.add(funcExpr); }  for (int i = 1; i < maxArgs; i++)
for (int i = 0; i < maxArgs; i++)
	private ExpressionTreeNode parseFactor(Preprocessor p) throws IOException, MapyrusException	{		boolean parsedDigit;		StringBuffer buf = new StringBuffer();		ExpressionTreeNode expr;		int c, quote;		boolean inOctalCode;		boolean inEscape;		int octalCode;		int nOctalDigits;		c = p.readNonSpace();		if (c == '\'' || c == '"')		{			/*			 * It's a quoted string.  Keep reading up until matching quote.			 */			quote = c;			inOctalCode = inEscape = false;			octalCode = nOctalDigits = 0;			while ((c = p.read()) != quote || inEscape)			{				if (c == -1)				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.UNEXPECTED_EOF));				}				if (inOctalCode)				{					/*					 * If next character is a digit then it is part of a					 * a '\nnn' octal character code.					 */					if (Character.isDigit((char)c) && nOctalDigits < 3)					{						octalCode *= 8;						octalCode += c - '0';						nOctalDigits++;					}					else					{						/*						 * Next character is not part of octal code.						 * Add character with octal code we've built						 * then return to regular parsing.						 */						buf.append((char)octalCode);						inOctalCode = false;					}				}				if (!inOctalCode)				{					if (inEscape)					{						/*						 * '\\' compressed to single backslash,						 * '\n' converted to a newline, '\r' is stripped -- it						 * is not useful since we use Java's line separator internally.						 * '\t" is converted to a tab.						 * '\367' is converted to character code (3 * 64) + (6 * 8) + 7.						 * Escaping of other characters is ignored.						 */						if (c == 'n')						{							buf.append(Constants.LINE_SEPARATOR);						}						else if (c == 't')						{							buf.append("\t");						}						else if (Character.isDigit((char)c))						{							inOctalCode = true;							octalCode = c - '0';							nOctalDigits = 1;						}						else if (c != 'r')						{							buf.append((char)c);						}						inEscape = false;					}					else if (c == '\\')					{						inEscape = true;					}					else					{						buf.append((char)c);					}				}			}			/*			 * Add any character we were building as octal code when quoted string finished.			 */			if (inOctalCode)				buf.append((char)octalCode);			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 == '_' || c == ':' ||				Character.isLetterOrDigit((char)c)))			{				buf.append((char)c);				c = p.read();			}			/*			 * Is this a function call like "round(3.14)"?			 */			Function f = FunctionTable.getFunction(buf.toString());			if (f != 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 minArgs = f.getMinArgumentCount();				int maxArgs = f.getMaxArgumentCount();				/*				 * Parse expression for each function argument.				 */				ArrayList functionExpressions = new ArrayList(4);				if (minArgs >= 0)				{					ExpressionTreeNode funcExpr = parseOrBoolean(p);					functionExpressions.add(funcExpr);				}				for (int i = 1; i < maxArgs; i++)				{					/*					 * Parse comma before next value, or closing bracket.					 */					c = p.readNonSpace();					if (i >= minArgs && c == ')')					{						p.unread(c);						break;					}					else if (c != ',')					{						throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +							": " + MapyrusMessages.get(MapyrusMessages.WRONG_FUNCTION_VALUES) +							": " + buf.toString());					}					ExpressionTreeNode funcExpr = parseOrBoolean(p);					functionExpressions.add(funcExpr);				}				/*				 * Read closing bracket.				 */				c = p.readNonSpace();				if (c != ')')				{					throw new MapyrusException(p.getCurrentFilenameAndLineNumber() +						": " + MapyrusMessages.get(MapyrusMessages.WRONG_FUNCTION_VALUES) +						": " + buf.toString());				}				expr = new ExpressionTreeNode(f, functionExpressions);			}			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);	}