/**
   This file contains an example use of the Minipar API. The program
   reads a sentence from the standard input one line at a time (upto
   1024 characters), treating each line as a sentence. The outputs of
   the program are the parse trees of the input sentences. Using the
   command line options one output the parse trees in constituency or
   dependency format and decide which features to include in the
   output.

   The printing routines in this file should provide some idea how to
   access the information contained in a ParseTree object.  */

#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;

//#include "quotewhite.h"
#define quote_white(x) x
#include "ptree.h"

const char *empty_cat_str = "()";

const int MAX_LINE_LEN=1024;

int PRINT_ROOT = 0;
int PRINT_RELATION = 0;
int PRINT_FEATURE = 0;
int INTERACTIVE = 0;
int HAS_COMMANDS = 0;
int PRINT_TRIPLES = 0;

void print_triples(const ParseNode* node)
{
  if (node->word() && *node->word()) {
    cout << "\t" << node->label() 
      << " [label=\"{" << quote_white(node->word())
      << "|{";
    if (node->root()) {
      cout << "<root>";
      if ((node->word() && strcasecmp(node->root(), node->word())==0))
	cout << '~';
      else
	cout << quote_white(node->root());
      cout
	<< "|";
    }
  cout
    << (node->category() ? node->category() : "U")
    << "|"
    << (node->relation() ? node->relation() : "")
    << "}}\"];\n";
  }
  ParseNode* parent = ((ParseNode*) node)->parent();
  if (!parent) {
    cout << "\t" << node->label() << " [label=\"*\"];" << endl;
  }
  else if (
      node->relation()
      && parent->root()
      && node->root()
      )
  {
      if (!node->antecedent()) {
	cout << "\t" << parent->label() << " -> " << node->label() 
	      << " [label=\"" << node->relation() << "\"];"
	    << endl;
      }
      else {
	cout << 
	  "\t" << parent->label() << " -> " << node->antecedent()->label() 
	    << " [style=dotted, "
	    << " label=\"" << node->relation()
	    << "\"];\n"; // antecedent
      }
  }
  else {
      cout << "\t" << parent->label() << " -> " << node->label() << " [style=dashed];"
	  << endl;
  }
  forall (ParseNode*, sub, TRSTree, node) {
    print_triples(sub);
  }
}

void print_dependency_node(const ParseNode* n)
{
  ParseNode* node = dynamic_cast(ParseNode*, n);
  if (node==node->tree()->root())
    return;
  cout << "\t" << node->label() << " [label=\"{";
  if ( (node->word() && *node->word()) )
    cout << quote_white(node->word());
  else
    cout << empty_cat_str;
  cout
    << "|{";
  if (node->root()) {
    cout << "<root>";
    if ((node->word() && strcasecmp(node->root(), node->word())==0))
      cout << '~';
    else
      cout << quote_white(node->root());

    cout
      << "|";
  }
  cout
    << (node->category() ? node->category() : "U")
    << "|"
    << (node->relation() ? node->relation() : "")
    << "}}\"];\n";
  if (node->parent() && node->parent()!=node->tree()->root()) {
    cout << 
      "\t" 
      << node->parent()->label()
      << " -> " 
      << node->label();
    if (node->parent() && node->parent()->root())
	cout << " [style=dashed]\n"; // gov
    cout
      << ";\n";
  }
  if (node->antecedent()) {
    cout << 
      "\t" << node->label() << " -> " << node->antecedent()->label() 
	<< " [dir=forward,style=dotted];\n"; // antecedent
  }
}

void print_dependency_tree(const ParseNode* n)
{
  int print_self = 0;
  if (n==0)
    return;
  ParseNode* node = dynamic_cast(ParseNode*, n);
  int pos = node->head_pos();
  forall (ParseNode*, sub, TRSTree, node) {
    int sub_pos = sub->head_pos();
    if (print_self==0 && sub_pos>=pos) {
      print_dependency_node(node);
      print_self = 1;
    }
    print_dependency_tree(sub);
  }
  if (!print_self)
    print_dependency_node(node);    
}

int main(int argc, char* argv[])
{
  char line[MAX_LINE_LEN+2];
  char* features=0;
  const char* paths = getenv("MINIPATH");

  for (int i = 1; i<argc; i++) {
    if (strcmp(argv[i], "-i")==0)
      INTERACTIVE = 1;
    else if (strcmp(argv[i], "-p")==0 && i<argc)
      paths = argv[++i];
    else if (strcmp(argv[i], "-t")==0) {
      PRINT_TRIPLES = 0;
    }
    else if (strcmp(argv[i], "-h")==0 || strcmp(argv[i], "-help")==0) {
      cout << "pdemo -i -p PATHS -t -h -help" << endl;
      cout << "  -i\tprint the prompt '> '" << endl;
      cout << "  -p PATHS\n\tdefine the search path" << endl;
      cout << "  -t print_dependency_tree/print_triples toggle" << endl;
      cout << "  -h or -help\n\tprint this help message" << endl;
    }
  }

  if (paths==0) {
    clog << "The search path for data files are not defined.\n ";
    clog << "You must use '-p PATHS' option or define the environment\n"
	 << "variable MINIPATH" << endl;
    exit(1);
  }

  initialize_minipar(paths);
  if (features)
    extract_features(features);

  ParseTree parsetree;
  if (INTERACTIVE)
    cout << "> " << flush;
  while (cin.getline(line, MAX_LINE_LEN)) {
    if (HAS_COMMANDS && line[0]=='~') {
      interpret_command_line(line+1);
    }
    else {
      static unsigned n = 0;
      parsetree.reset();
      parse(line, parsetree);
      cout <<
	"digraph G" << ++n << " {\n"
	  "\tordering=out;\n"
	  "\tlabel=\"" << line << "\"\n"
	  "\tnode [shape=Mrecord];\n";
      if (PRINT_TRIPLES) 
	print_triples(parsetree.root());
      else {
	cout << "\tnode [dir=back];\n";
	print_dependency_tree(parsetree.root());
      }
      cout << "}" << endl;
    }
    if (INTERACTIVE)
      cout << "> " << flush;
  }
}
// vim:ts=8:sts=2:sw=2

