package JavaAgent.resource.cdl;

import java.io.*;

/**
** This class is a special reader that takes an InputStream and gets complete
** expressions from that stream. As there is no syntax for expressions all
** the reader does is count the number of brackets to determine where an
** expressions begins and ends.
*/

public class ExpressionReader extends InputStreamReader {

  /**
  ** The constructor for an ExpressionReader takes an InputStream and
  ** calls the according constructor for an InputStreamReader.
  ** @param in the InputStream expressions are to be read from
  */
  public ExpressionReader(InputStream in) {
    super(in);
  }

  /**
  ** This function gets the next expression from the InputStream of this
  ** ExpressionReader. It ignores all characters until it finds an open 
  ** bracket (round, square, or curly). This is where the expression starts.
  ** It will keep reading until the matching brcket is found and the 
  ** expression ends there. However, this function only counts brackets and
  ** the type of bracket (round, square, or curly) is ignored. If no more 
  ** expression can be read the result will be null.
  ** @return the String representing the next expression or <tt>null</tt>
  ** @exception IOException An exception can occur if reading from the given
  ** InputStream fails or the stream finishes before a matching closing
  ** bracket in an expression has been found.
  */
  public String readExpression() throws IOException {

    // read characters until there is an open bracket:
    do {
      nextCh = (char)read();
    } while (!eofChar() && !openBracket());
    if (eofChar())
      return null;

    // now read until the matching bracket has been found:
    String result = new String();
    int brCount = 1;
    while (brCount > 0) {
      if ((nextCh != '\n') && !((nextCh == ' ') && (prevCh == ' ')))
	result += nextCh;
      prevCh = nextCh;
      nextCh = (char)read();
      if (eofChar())
	throw new IOException("Unexpected end of expression.");
      if (openBracket())
	brCount++;
      if (closeBracket())
	brCount--;
    }
    return result + nextCh;
  }

  private boolean eofChar() {
    return ((nextCh > 32767) || (nextCh < 0));
  }

  private boolean openBracket() {
    return ((nextCh == '(') || (nextCh == '[') || (nextCh == '{'));
  }

  private boolean closeBracket() {
    return ((nextCh == ')') || (nextCh == ']') || (nextCh == '}'));
  }

  private char nextCh = 0;
  private char prevCh = 0;
}
