// Goldie: GOLD Engine for D
// Tools: GRMC: Grammar Compiler
// Written in the D programming language.

module tools.grmc.cmd;

import std.array;
import std.path;
import std.stdio;
import std.string;

import semitwist.cmdlineparser;
import semitwist.util.all;

import goldie.all;
import tools.util;

class CmdArgs
{
	mixin(getter!(bool, "shouldExit"));

	public this(string[] args)
	{
		init();
		shouldExit = !parse(args);
	}
	
	// Direct command-line args (may be baked, not guaranteed to be raw)
	public bool   help;
	public bool   detailhelp;
	public string grmFile;
	public string cgtFile = "";
	public bool   verbose;
	public bool   goldCompat;
	public bool   dot;

	// Private ------
	private CmdLineParser cmd;
	
	private void init()
	{
		cmd = new CmdLineParser();
		mixin(defineArg!(cmd, "help",   help,       ArgFlag.Optional, "Displays a help summary and exits" ));
		mixin(defineArg!(cmd, "detail", detailhelp, ArgFlag.Optional, "Displays a detailed help message and exits" ));
		mixin(defineArg!(cmd, "",       grmFile,    ArgFlag.Required, "Grammar definition in .grm format" ));
		mixin(defineArg!(cmd, "o",      cgtFile,    ArgFlag.Optional, "Output filename" ));
		mixin(defineArg!(cmd, "v",      verbose,    ArgFlag.Optional, "Verbose" ));
		mixin(defineArg!(cmd, "gold",   goldCompat, ArgFlag.Optional, "Imitate GOLD's output as closely as possible" ));
		mixin(defineArg!(cmd, "dot",    dot,        ArgFlag.Optional, "Output lexer's NFA and DFA to Graphviz DOT format" ));
	}
	
	// Returns: Should processing proceed? If false, the program should exit.
	private bool parse(string[] args)
	{
		enum info =
			helpInfoHeader("GRMC: Grammar Compiler", "2010-2011 Nick Sabalausky") ~
			"\n\n" ~
			"Compiles a GOLD .grm grammar definition file to .cgt";
			
		enum sampleUsageMsg = `
			Usage: goldie-grmc grammar.grm
			       goldie-grmc grammar.grm -o:output.cgt
		`.normalize();
		
		cmd.parse(args);
		if(detailhelp)
		{
			writeln(info);
			writeln();
			writeln(sampleUsageMsg);
			write(cmd.getDetailedUsage());
			return false;
		}
		if(!cmd.success || help)
		{
			writeln(info);
			writeln();
			writeln(sampleUsageMsg);
			writeln();
			write(cmd.getUsage(13));
			if(!help)
			{
				writeln();
				write(cmd.errorMsg);
			}
			return false;
		}
		
		if(cgtFile == "")
			cgtFile = grmFile.basename().getName()~".cgt";

		return true;
	}
}
