#include <stdio.h>

#include <string>
#include <list>
#include <iostream>

using namespace std;

#include "xapian.h"

const char *vals[] = {"un", "deux", "trois", "quatre"};
int nvals = sizeof(vals) / sizeof(int);

int main(int argc, char **argv)
{
  string ermsg;
  list<string> strs; 
  for (unsigned int i = 0; i < nvals; i++)
      strs.push_back(vals[i]);

  try {
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query(Xapian::Query::OP_NEAR, 
				     Xapian::Query("A"), 
				     Xapian::Query("B")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_NEAR, 
				     Xapian::Query("C"), 
				     Xapian::Query("D")));

	  Xapian::Query q(Xapian::Query::OP_OR, ql.begin(), ql.end());
	  fprintf(stderr, "(A NEAR B) OR (C NEAR D) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query("A"));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("B"),
				     Xapian::Query("C")));
	  ql.push_back(Xapian::Query("D"));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "A NEAR (B OR C) NEAR D ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query("A"));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("B"),
				     Xapian::Query("C")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("D"),
				     Xapian::Query("E")));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "A NEAR (B OR C) NEAR (D OR E) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("A"),
				     Xapian::Query("B")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("C"),
				     Xapian::Query("D")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("E"),
				     Xapian::Query("F")));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "(A OR B) NEAR (C OR D) NEAR (E OR F) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query(Xapian::Query::OP_AND, 
				     Xapian::Query("A"),
				     Xapian::Query("B")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("C"),
				     Xapian::Query("D")));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "(A AND B) NEAR (C OR D) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("A"),
				     Xapian::Query("B")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_AND, 
				     Xapian::Query("C"),
				     Xapian::Query("D")));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "(A OR B) NEAR (C AND D) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }

      {
	  vector<Xapian::Query> ql;
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     Xapian::Query("A"),
				     Xapian::Query("B")));
	  ql.push_back(Xapian::Query(Xapian::Query::OP_OR, 
				     strs.begin(),
				     strs.end()));
	  Xapian::Query q(Xapian::Query::OP_NEAR, ql.begin(), ql.end());
	  fprintf(stderr, "(A OR B) NEAR (ORlist) ->\n  %s\n\n", 
		  q.get_description().c_str());
      }
      {
	  Xapian::Query q1(Xapian::Query::OP_OR, 
			   Xapian::Query("A"),
			   Xapian::Query("B"));
	  Xapian::Query q2(Xapian::Query::OP_OR, 
			   Xapian::Query("C"),
			   Xapian::Query("D"));
	  Xapian::Query q3(Xapian::Query::OP_AND, q1, q2);

	  Xapian::Query q4(Xapian::Query::OP_OR, 
			   Xapian::Query("E"),
			   Xapian::Query("F"));
	  Xapian::Query q5(Xapian::Query::OP_OR, 
			   Xapian::Query("G"),
			   Xapian::Query("H"));
	  Xapian::Query q6(Xapian::Query::OP_AND, q4, q5);

	  Xapian::Query q(Xapian::Query::OP_NEAR, q3, q6);
	  fprintf(stderr, 
		  "((A OR B) AND (C OR D)) NEAR ((E OR F) AND (G OR H)) ->\n"
		  "  %s\n\n", q.get_description().c_str());
      }

  } catch (const Xapian::Error &e) {
      ermsg = e.get_msg();
  } catch (const string &s) {
      ermsg = s;
  } catch (const char *s) {
      ermsg = s;
  } catch (...) {
      ermsg = "Caught unknown exception";
  }
  if (!ermsg.empty()) {
      cerr << ermsg << endl;
  }
  exit(0);
}

