/* This software is distributed under the Lesser General Public License */
//
// Parser.cc
//
// This file implements the classes GT_Parser and GT_Parser_yacc.
//
//------------------------------------------
//
// $Source: /home/br/CVS/graphlet/src/gt_base/Parser.cpp,v $
// $Author: himsolt $
// $Revision: 1.4 $
// $Date: 1999/03/05 20:44:31 $
// $Locker:  $
// $State: Exp $
//
//------------------------------------------
//
// (C) University of Passau 1995-1999, graphlet Project
//


#include "Graphlet.h"

#include "Attributes.h"
#include "List_of_Attributes.h"
#include "Attribute_int.h"
#include "Attribute_double.h"
#include "Attribute_string.h"
#include "Attribute_list.h"

#include "gml_parser.h"
#include "Parser.h"
#include <strstream>

//////////////////////////////////////////
//
// class GT_Parser
//
//////////////////////////////////////////


GT_CLASS_IMPLEMENTATION (GT_Parser);


GT_Parser::GT_Parser()
{
    the_parsed_attrs = 0;
    the_error_while_parsing = false;
}


GT_Parser::~GT_Parser()
{
}


//
// Needed for debugging
//

// static void print_keys (struct GML_list_elem* gml_list)
// {   
//     while (gml_list) {
// 	printf ("%s\n", gml_list->key);
// 	gml_list = gml_list->next;
//     }
// }


// void GT_Parser::GML_to_Graphlet (struct GML_pair* list,
//     GT_List_of_Attributes* top)
// {
//     struct GML_pair* tmp = list;
//     int i;


//     while (tmp) {

// 	GT_List_of_Attributes* sublist = 0;
// 	GT_Attribute_Base* a = 0;
	
// 	switch (tmp->kind) {
// 	case GML_INT:
// 	    a = new GT_Attribute_int (
//                 graphlet->keymapper.add (tmp->key),
//                 tmp->value.integer);
// 	    top->push_back (a);
// 	    break;

// 	case GML_DOUBLE:
// 	    a = new GT_Attribute_double (
//                 graphlet->keymapper.add (tmp->key),
//                 tmp->value.floating);
// 	    top->push_back (a);
// 	    break;

// 	case GML_STRING:
// 	    a = new GT_Attribute_string (
//                 graphlet->keymapper.add (tmp->key),
//                 tmp->value.string);
// 	    top->push_back (a);
// 	    break;
	    
// 	case GML_LIST:
// 	    sublist = new GT_List_of_Attributes;
// 	    GML_to_Graphlet (tmp->value.list, sublist);
// 	    a = new GT_Attribute_list (
// 		graphlet->keymapper.add (tmp->key),
// 		sublist);
// 	    top->push_back (a);
// 	    break;

// 	default:
// 	    cerr << "ERRROR" << endl;
// 	    break;
// 	}
	
// 	tmp = tmp->next;
//     }
// }



GT_List_of_Attributes* GT_Parser::parser (
    const char* filename)
{
    //
    // Reset parser
    //

    the_error_while_parsing = false;
    the_error_message = "";
    the_parsed_attrs = 0;
    the_line_number = 1;
	
#if 0
    extern int yyparse(); // generated by yacc  or bison
    extern FILE* yyin;

    if (filename != 0 && strcmp (filename, "")) {

	// open filename and read from it
		
	FILE* file = graphlet->fopen (filename, "r");
	if (file != 0) {
	    yyin = file;
	    yyparse();
	    graphlet->fclose (file);
	}
		
    } else {

	// read from standard input (?)

	yyin = stdin;
	yyparse();
    }
#endif

    FILE* file;
    if (filename != 0 && strcmp (filename, "")) {
	file = graphlet->fopen (filename, "r");
    } else {
	file = stdin;
    }
	
    // open filename and read from it
		
    if (file != 0) {

	struct GML_stat stat;
	stat.key_list = NULL;
	GML_init ();
	the_parsed_attrs = GT_GML_parser (file, &stat);
	if (file != stdin) {
	    graphlet->fclose (file);
	}
	
	if (stat.err.err_num != GML_OK) {

	    the_error_while_parsing = true;
	    the_line_number = stat.err.line;
	    the_column_number = stat.err.column;

	    ostrstream s;
	    s << "File "	<< filename
	      << " Line "	<< stat.err.line
	      << " Column "	<< stat.err.column
	      << ":\n";
	    
	    the_error_message = GT::format ("File %s Line %d Column %d:\n",
		filename,
		stat.err.line,
		stat.err.column);
	    
	    switch (stat.err.err_num) {
		case GML_UNEXPECTED:
		    the_error_message += "UNEXPECTED CHARACTER\n";
		    break;
		    
		case GML_SYNTAX:
		    the_error_message += "SYNTAX ERROR\n"; 
		    break;
		    
		case GML_PREMATURE_EOF:
		    the_error_message += "PREMATURE EOF IN STRING\n";
		    break;
		    
		case GML_TOO_MANY_DIGITS:
		    the_error_message += "NUMBER WITH TOO MANY DIGITS\n";
		    break;
		    
		case GML_OPEN_BRACKET:
		    the_error_message += "OPEN BRACKETS LEFT AT EOF\n";
		    break;
		    
		case GML_TOO_MANY_BRACKETS:
		    the_error_message += "TOO MANY CLOSING BRACKETS\n";
		    break;
		
		default:
		    break;
	    }

	} 

#ifdef GML_DEBUG
	printf ("Keys used in %s: \n", filename);
	print_keys (stat.key_list);
#endif
    }

    return parsed_attrs();
}



//////////////////////////////////////////
//
// class GT_Parser_yacc
//
// Gone for good
//
//////////////////////////////////////////


// GT_CLASS_IMPLEMENTATION (GT_Parser_yacc);


// GT_Parser_yacc::GT_Parser_yacc()
// {
// }


// GT_Parser_yacc::~GT_Parser_yacc()
// {
// }


// int GT_Parser_yacc::error (int line_number, const char *str)
// {
//     assert (str != 0);
    
//     the_error_while_parsing = true;
//     the_error_message = string ("Line %d: Error: %s", line_number, str);
    
//     return 42; // dummy; the function expects a value, so return one
// }
