/*******************************************************************/
/*      File: print-YAP.h                                          */
/*    Author: Helmut Schmid                                        */
/*   Purpose: print functions                                      */
/*   Created: Tue Dec 10 14:05:15 2002                             */
/*  Modified: Thu Jan 15 09:00:02 2009 (schmid)                    */
/* Copyright: Institut fuer maschinelle Sprachverarbeitung         */
/*            Universitaet Stuttgart                               */
/*******************************************************************/

#include "quote.h"

static int Current_ID;
static bool *Visited;
static int *NodeID;
static int  *StartPos;
static int  *EndPos;
FILE *Outfile;


/*******************************************************************/
/*                                                                 */
/*  annotate_node                                                  */
/*                                                                 */
/*******************************************************************/

static int annotate_node( Node node, int pos )

{
  if (!Visited[node.number()]) {
    Visited[node.number()] = true;

    if (!node.is_aux())
      NodeID[node.number()] = Current_ID++;
    StartPos[node.number()] = pos;

    for( Node::iterator it=node.begin(); it!=node.end(); ++it ) {
      Edge edge=*it;
      if (edge.is_terminal())
	EndPos[node.number()] = StartPos[node.number()] + 1;
      else {
	pos = StartPos[node.number()];
	for( Edge::iterator it=edge.begin(); it!=edge.end(); ++it ) {
	  Node daughter=*it;
	  pos = annotate_node(daughter, pos);
	}
	EndPos[node.number()] = pos;
      }
    }
  }
  return EndPos[node.number()];
}


/*******************************************************************/
/*                                                                 */
/*  print_YAP_daughters                                            */
/*                                                                 */
/*******************************************************************/

static void print_YAP_daughters( Node node, vector<int> &currana, 
				 vector<int> &maxana, size_t &n )
{
  if (currana.size() == n) {
    currana.push_back(0);
    maxana.push_back((int)node.size());
  }
  Edge edge=node.edge(currana[n]);
  if (edge.is_terminal())
    fprintf(Outfile, "\"%s\" ", quote(edge.word()));
  else {
    if (n == 0)
      fprintf(Outfile, " %d", edge.source_rule_number());
    for( Edge::iterator it=edge.begin(); it!=edge.end(); ++it ) {
      Node daughter=*it;
      if (daughter.is_aux())
	print_YAP_daughters(daughter, currana, maxana, ++n);
      else
	fprintf(Outfile, " %d", NodeID[daughter.number()]);
    }
  }
}


/*******************************************************************/
/*                                                                 */
/*  print_YAP_node                                                 */
/*                                                                 */
/*******************************************************************/

static void print_YAP_node( Node node )

{
  if (node.is_aux())
    return;

  fprintf(Outfile, "\n%s %d %d\t", node.symbol_name(), 
	  StartPos[node.number()], EndPos[node.number()]);
  vector<int> currana, maxana;
  do {
    size_t n=0;
    print_YAP_daughters( node, currana, maxana, n );
    fputs(" %", Outfile);
  } while (next_combination(currana, maxana));
  fputc('%', Outfile);
}


/*******************************************************************/
/*                                                                 */
/*  Parser::print_YAP_parse                                        */
/*                                                                 */
/*******************************************************************/

void Parser::print_YAP_parse( FILE *file )

{
  if (parse.number_of_nodes() == 0) {
    failure_output( file );
    return;
  }

  Visited = new bool[parse.number_of_nodes()];
  for( size_t i=0; i<parse.number_of_nodes(); i++ )
    Visited[i] = false;
  Current_ID = 0;
  NodeID   = new int[parse.number_of_nodes()];
  StartPos = new int[parse.number_of_nodes()];
  EndPos   = new int[parse.number_of_nodes()];

  for( iterator it=begin(); it!=end(); ++it ) {
    Node root = *it;
    annotate_node(root, 0);
  }
  delete[] Visited;

  Outfile = file;
  apply(print_YAP_node, NULL, NULL, NULL, NULL, NULL);
  fputs("%\n",file);

  delete[] NodeID;
  delete[] StartPos;
  delete[] EndPos;
}
