Skip to content
Snippets Groups Projects
main.cpp 5.87 KiB
Newer Older
ilor's avatar
ilor committed
#include <fstream>
#include <iomanip>


#include <libwccl/values/strset.h>
#include <libwccl/parser/Parser.h>
#include <libcorpus2/tagsetmanager.h>

#include <boost/bind.hpp>
#include <boost/program_options.hpp>
ilor's avatar
ilor committed
#include <libcorpus2/io/xcesreader.h>

#include <antlr/MismatchedTokenException.hpp>
// ----------------------------------------------------------------------------

#ifdef HAVE_LIBEDIT

/**
 * @desc A simple command line tester for testing operators
 */


namespace {
	const char* _prompt = "Enter any operator expression: ";
}

void std_read_loop(boost::function<bool (const std::string&)>& line_cb)
{
	while (std::cin.good()) {
		std::cout << _prompt << std::flush;
		std::string s;
		getline(std::cin, s);
		if (line_cb(s)) {
			return;
		}
	}
}

int clear_screen()
{
#ifdef _WINDOWS
	return std::system("cls");
#else
	return std::system("clear");
#endif
}

#ifdef HAVE_LIBEDIT
const char* query_prompt(EditLine*) {
	return _prompt;
}

void libedit_read_loop(boost::function<bool (const std::string&)>& line_cb)
{
	EditLine *el = el_init("wccl-parser", stdin, stdout, stderr);
	el_set(el, EL_PROMPT, &query_prompt);
	el_set(el, EL_EDITOR, "emacs");
	History* myhistory = history_init();
	if (myhistory == NULL) {
		std::cerr << "EditLine history init error\n";
		el_end(el);
		std_read_loop(line_cb);
		return;
	}
	HistEvent ev;
	history(myhistory, &ev, H_SETSIZE, 1024);
	el_set(el, EL_HIST, history, myhistory);

	bool more = true;
	while (more) {
		int count;
		const char *line = el_gets(el, &count); // line gets a trailing \n
		if (line == NULL || line[0] == 0) {
			more = false;
		} else {
			std::string s(line, strlen(line) - 1);
			if (line_cb(s)) {
				more = false;
			} else {
				history(myhistory, &ev, H_ENTER, line);
			}
		}
	}

	history_end(myhistory);
	el_end(el);
}
#endif

bool process_line(const std::string& line, Parser& parser,
	Wccl::SentenceContext& sc, bool all_positions)
{
	if (line.empty() || line == "exit" || line == "quit") {
		return true;
	} else if (line == "clear" || line == "cls") {
		if (clear_screen()) {}
		return false;
	}

	boost::shared_ptr<const Wccl::Value> retVal;
	boost::shared_ptr<ANTLRParserResultBase> retOp;
	try {
		retOp = parser.parseAnyOperator(line);
		if (retOp) {
			int pb, pe;
			if (all_positions) {
				pb = 0;
				pe = sc.get_sentence().empty() ? 1 : sc.size();
				pb = sc.get_position();
				pe = sc.get_position() + 1;
			}
			for (int i = pb; i < pe; ++i) {
				sc.set_position(i);
				Wccl::FunExecContext cx(sc,
					boost::shared_ptr<Wccl::Variables>(retOp->variables->clone()));
				retVal = retOp->get_op_base()->apply_internal(cx);
				if (retVal) {
					std::cerr << "[" << std::setw(2) << sc.get_position() << "] "
						<< "Parsed expression: "
						<< retVal->to_string(parser.tagset())
						<< std::endl;
				} else {
					std::cerr << "Problem while parsing -- "
						<< "retVal is NULL!" << std::endl;
				}
			}
		} else {
			std::cerr << "Problem while parsing -- "
				<< "parser returned NULL!" << std::endl;
		}
	} catch (antlr::MismatchedTokenException &e) {
		std::cerr << e.getMessage() << std::endl;
	} catch (Wccl::InvalidVariableName &e) {
		std::cerr << "Wccl::InvalidVariableName " << e.info() << std::endl;
	} catch (Wccl::VariableTypeMismatch &e) {
		std::cerr << "Wccl::VariableTypeMismatch " << e.info() << std::endl;
	} catch (Wccl::WcclError& e) {
		std::cerr << "Wccl::WcclError " << e.info() << std::endl;
	} catch (PwrNlp::PwrNlpError& e) {
		std::cerr << "PwrNlp::PwrNlpError " << e.info() << std::endl;
	} catch (antlr::ANTLRException& e) {
		std::cerr << "Antlr error " << e.getMessage() << std::endl;
	}
	return false;
}

int main(int argc, char** argv)
	std::string tagset_load = "kipi";
ilor's avatar
ilor committed
	std::string sentence_load = "";
	std::string position = "0";
	bool quiet = false;
	using boost::program_options::value;

	boost::program_options::options_description desc("Allowed options");
	desc.add_options()
			("tagset,t", value(&tagset_load),
			 "Tagset to use\n")
ilor's avatar
ilor committed
			("sentence,s", value(&sentence_load),
			 "Sentence to load (XCES)\n")
			("position,p", value(&position),
			 "Position in the sentence to use, 'all' iterates through the sentence\n")
			("query,Q", value(&query),
			 "Query to run (disables interactive mode)\n")
			("quiet,q", value(&quiet)->zero_tokens(),
			 "Suppress messages\n")
			("help,h", "Show help")
			;
	boost::program_options::variables_map vm;
	boost::program_options::positional_options_description p;

	try {
		boost::program_options::store(
			boost::program_options::command_line_parser(argc, argv)
			.options(desc).positional(p).run(), vm);
	} catch (boost::program_options::error& e) {
		std::cerr << e.what() << std::endl;
		return 2;
	}
	boost::program_options::notify(vm);

	if (vm.count("help")) {
		std::cout << desc << "\n";
		return 1;
	}

ilor's avatar
ilor committed
		const Corpus2::Tagset& tagset = Corpus2::get_named_tagset(tagset_load);
		boost::shared_ptr<Corpus2::Sentence> sentence;
		if (sentence_load.empty()) {
			sentence.reset(new Corpus2::Sentence);
		} else {
			std::ifstream ifs(sentence_load.c_str());
			if (ifs.good()) {
				Corpus2::XcesReader reader(tagset, ifs, false);
				sentence.reset(reader.get_next_sentence());
				std::cerr << "Sentence loaded, " << sentence->size()
					<< " tokens.\n";
			} else {
				throw Wccl::FileNotFound(sentence_load, "", "Sentence");
			}
		}
		Wccl::SentenceContext sc(sentence);
		int pos = atoi(position.c_str());
		sc.set_position(pos);
		Parser parser(tagset);
		if (!query.empty()) {
			process_line(query, parser, sc, position == "all");
ilor's avatar
ilor committed
			return 0;
		}
		boost::function<bool (const std::string&)> f;
		f = boost::bind(&process_line, _1, boost::ref(parser), boost::ref(sc),
			position == "all");
ilor's avatar
ilor committed
		libedit_read_loop(f);
ilor's avatar
ilor committed
		std_read_loop(f);
ilor's avatar
ilor committed
	} catch (PwrNlp::PwrNlpError& e) {
		std::cerr << e.info() << std::endl;
		return 2;
	}