// (c) MIT 2003.  All rights reserved.

///////////////////////////////////////////////////////////////////////////////
//
// FILE:	FileParser.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	January, 1999
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:     File consisting of strings to be parsed;
//                useful for initialization files
//
///////////////////////////////////////////////////////////////////////////////

package rec.util;

import java.util.*;
import java.io.*;

/**
 * FileParser passes each of its lines to Parser classes
 *   which then process them;
 * The Parser classes are added to the FileParser in the
 *   order that parsing is desired;
 * If a line cannot be parsed a parser error will be thrown;
 **/
public class FileParser
{
  public FileParser()
  {
    // the lineParsers Vector can be modified externally
    m_LineParsers = new Vector();
  }

  public FileParser( Vector lineParsers )
  {
    // the lineParsers Vector can be modified externally
    m_LineParsers = lineParsers;
  }

  /////////////////////////////////////////////////////////////////////////////

  public Vector getLineParsers()
  {
    return( m_LineParsers );
  }

  public void setLineParsers( Vector lineParsers )
  {
    m_LineParsers = lineParsers;
  }

  public void addParser( LineParser lp )
  {
    m_LineParsers.addElement( lp );
  }

  /////////////////////////////////////////////////////////////////////////////

  public boolean parseFile( String fileName )
  {
    BufferedReader br = null;

    try {

      br = new BufferedReader( new FileReader( fileName.trim() ) );
    }
    catch( FileNotFoundException e ) {
      return( false );
    }

    String nextLine = null;

    try {

      while( (nextLine = br.readLine()) != null ) {

	if( !parseLine( nextLine ) ) {
	  br.close();
	  return( false );
	}
      }
    }
    catch( IOException e ) {
      return( false );
    }

    try {
      br.close();
    }
    catch( IOException e ) {
      return( false );
    }

    return( true );
  }

  /////////////////////////////////////////////////////////////////////////////

  private boolean parseLine( String line ) throws IOException
  {
    String command = line.trim();

    if( isEmpty( command ) )
      return( true );

    if( isComment( command ) )
      return( true );

    String[] args = getArguments( command );

    Assert.check( args != null, "implementation error" );

    for( int i = 0; i < m_LineParsers.size(); ++i ) {

      LineParser lp = (LineParser)m_LineParsers.elementAt( i );

      if( lp.isValid( args ) ) {
	lp.execute( args );
	return( true );
      }
    }

    // unparsable line
    return( false );
  }

  //////////////////////////////////////////////////////////////////////////////

  private static String[] getArguments( String line ) throws IOException
  {
    Vector args = new Vector();

    StreamTokenizer st = new StreamTokenizer( new StringReader( line ) );

    st.commentChar( '#' );
    st.quoteChar( '"' );
    st.whitespaceChars( ':', ':' );

    st.nextToken();
    
    while( st.ttype != StreamTokenizer.TT_EOF )
      {
	args.addElement( st.sval.toString() );
	st.nextToken();
      }

    if( args.size() == 0 )
      return( null );

    String[] ret = new String[args.size()];

    for( int i = 0; i < args.size(); ++i )
      ret[i] = (String)args.elementAt( i );

    return( ret );
  }

  //////////////////////////////////////////////////////////////////////////////

  private static boolean isEmpty( String command )
  {
    if( command.equals( "" ) )
      return( true );

    return( false );
  }

  private static boolean isComment( String command )
  {
    if( isEmpty( command ) )
      return( false );

    if( command.charAt( 0 ) == '#' )
      return( true );

    return( false );
  }

  //////////////////////////////////////////////////////////////////////////////

  private Vector m_LineParsers;
}

////////////////////////////////////////////////////////////////////////////////
