/// This module was generated by the StaticLang tool from
/// Goldie v0.4: http://www.semitwist.com/goldie/

// Goldie: GOLD Engine for D
// Written in the D programming language.

module samples.calculatorStatic.calc.lang;

version = GoldieStaticLang;

import std.stdio;
import std.string;

import semitwist.util.all;

import goldie.base;

import goldie.exception;
import goldie.lexer;
import goldie.parser;
import goldie.token;

import goldie.grmc.ast;
import goldie.langs.grm.all;

//TODO: Create a function to fix symbolLookup after changing the language details.
//      Maybe cause the accessors to set a "dirty" flag which will re-gen symbolLookup
//      next time symbolLookup is accessed.
//TODO: In SemiTwistLib, create an "accessor"/"property" mixin similar to "getter"

version(GoldieStaticLang)
{
	import goldie.lang;
	
	import samples.calculatorStatic.calc.lexer;
	import samples.calculatorStatic.calc.parser;

	// This mess is a workaround for the cyclic dependency probelms in static constructors
	private Language_calc language_calc_;
	private bool isInited = false;
	public @property ref Language_calc language_calc()
	{
		if(!isInited)
		{
			language_calc_ = new Language_calc();
			isInited = true;
		}
		return language_calc_;
	}
	/+static this()
	{
		language_calc = new Language_calc();
	}+/
}

public class Language_calc : Language
{
	
	
	static enum staticName   = "Calc";
	static enum staticVer    = "0.01";
	static enum staticAuthor = "Nick Sabalausky";
	static enum staticAbout  = "Basic Calculator Grammar";
	static enum staticCaseSensitive = false;

	static enum staticStartSymbolIndex = 10;
	static enum staticInitialDFAState  = 0;
	static enum staticInitialLALRState = 0;
	static enum staticEofSymbolIndex   = 0;
	static enum staticErrorSymbolIndex = 1;

	static enum staticUniqueSymbolNameArray = [
		"(",
		")",
		"*",
		"+",
		"-",
		"/",
		"<Add Exp>",
		"<Mult Exp>",
		"<Negate Exp>",
		"<Value>",
		"EOF",
		"Error",
		"Number",
		"Whitespace",
	];

	static enum staticSymbolTable = [
		Symbol("EOF",SymbolType.EOF,0),
		Symbol("Error",SymbolType.Error,1),
		Symbol("Whitespace",SymbolType.Whitespace,2),
		Symbol("-",SymbolType.Terminal,3),
		Symbol("(",SymbolType.Terminal,4),
		Symbol(")",SymbolType.Terminal,5),
		Symbol("*",SymbolType.Terminal,6),
		Symbol("/",SymbolType.Terminal,7),
		Symbol("+",SymbolType.Terminal,8),
		Symbol("Number",SymbolType.Terminal,9),
		Symbol("<Add Exp>",SymbolType.NonTerminal,10),
		Symbol("<Mult Exp>",SymbolType.NonTerminal,11),
		Symbol("<Negate Exp>",SymbolType.NonTerminal,12),
		Symbol("<Value>",SymbolType.NonTerminal,13),
	];
	
	static enum staticCharSetTable = [
		CharSet("\t\n\r  "d),
		CharSet("-"d),
		CharSet("("d),
		CharSet(")"d),
		CharSet("*"d),
		CharSet("/"d),
		CharSet("+"d),
		CharSet("0123456789"d),
	];
	
	static enum staticRuleTable = [
		Rule( 10, [10,8,11] ),
		Rule( 10, [10,3,11] ),
		Rule( 10, [11] ),
		Rule( 11, [11,6,12] ),
		Rule( 11, [11,7,12] ),
		Rule( 11, [12] ),
		Rule( 12, [3,13] ),
		Rule( 12, [13] ),
		Rule( 13, [9] ),
		Rule( 13, [4,10,5] ),
	];
	
	static enum staticDFATable = [
		DFAState( false, -1, [DFAStateEdge(0,1),DFAStateEdge(1,2),DFAStateEdge(2,3),DFAStateEdge(3,4),DFAStateEdge(4,5),DFAStateEdge(5,6),DFAStateEdge(6,7),DFAStateEdge(7,8)] ),
		DFAState( true, 2, [DFAStateEdge(0,1)] ),
		DFAState( true, 3, [] ),
		DFAState( true, 4, [] ),
		DFAState( true, 5, [] ),
		DFAState( true, 6, [] ),
		DFAState( true, 7, [] ),
		DFAState( true, 8, [] ),
		DFAState( true, 9, [DFAStateEdge(7,8)] ),
	];
	
	static enum staticLALRTable = [
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(10,LALRAction.Type.Goto,4),LALRAction(11,LALRAction.Type.Goto,5),LALRAction(12,LALRAction.Type.Goto,6),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(13,LALRAction.Type.Goto,8)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(10,LALRAction.Type.Goto,9),LALRAction(11,LALRAction.Type.Goto,5),LALRAction(12,LALRAction.Type.Goto,6),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,8),LALRAction(3,LALRAction.Type.Reduce,8),LALRAction(5,LALRAction.Type.Reduce,8),LALRAction(6,LALRAction.Type.Reduce,8),LALRAction(7,LALRAction.Type.Reduce,8),LALRAction(8,LALRAction.Type.Reduce,8)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Accept,0),LALRAction(3,LALRAction.Type.Shift,10),LALRAction(8,LALRAction.Type.Shift,11)] ),
		LALRState( [LALRAction(6,LALRAction.Type.Shift,12),LALRAction(7,LALRAction.Type.Shift,13),LALRAction(0,LALRAction.Type.Reduce,2),LALRAction(3,LALRAction.Type.Reduce,2),LALRAction(5,LALRAction.Type.Reduce,2),LALRAction(8,LALRAction.Type.Reduce,2)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,5),LALRAction(3,LALRAction.Type.Reduce,5),LALRAction(5,LALRAction.Type.Reduce,5),LALRAction(6,LALRAction.Type.Reduce,5),LALRAction(7,LALRAction.Type.Reduce,5),LALRAction(8,LALRAction.Type.Reduce,5)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,7),LALRAction(3,LALRAction.Type.Reduce,7),LALRAction(5,LALRAction.Type.Reduce,7),LALRAction(6,LALRAction.Type.Reduce,7),LALRAction(7,LALRAction.Type.Reduce,7),LALRAction(8,LALRAction.Type.Reduce,7)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,6),LALRAction(3,LALRAction.Type.Reduce,6),LALRAction(5,LALRAction.Type.Reduce,6),LALRAction(6,LALRAction.Type.Reduce,6),LALRAction(7,LALRAction.Type.Reduce,6),LALRAction(8,LALRAction.Type.Reduce,6)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,10),LALRAction(5,LALRAction.Type.Shift,14),LALRAction(8,LALRAction.Type.Shift,11)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(11,LALRAction.Type.Goto,15),LALRAction(12,LALRAction.Type.Goto,6),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(11,LALRAction.Type.Goto,16),LALRAction(12,LALRAction.Type.Goto,6),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(12,LALRAction.Type.Goto,17),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(3,LALRAction.Type.Shift,1),LALRAction(4,LALRAction.Type.Shift,2),LALRAction(9,LALRAction.Type.Shift,3),LALRAction(12,LALRAction.Type.Goto,18),LALRAction(13,LALRAction.Type.Goto,7)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,9),LALRAction(3,LALRAction.Type.Reduce,9),LALRAction(5,LALRAction.Type.Reduce,9),LALRAction(6,LALRAction.Type.Reduce,9),LALRAction(7,LALRAction.Type.Reduce,9),LALRAction(8,LALRAction.Type.Reduce,9)] ),
		LALRState( [LALRAction(6,LALRAction.Type.Shift,12),LALRAction(7,LALRAction.Type.Shift,13),LALRAction(0,LALRAction.Type.Reduce,1),LALRAction(3,LALRAction.Type.Reduce,1),LALRAction(5,LALRAction.Type.Reduce,1),LALRAction(8,LALRAction.Type.Reduce,1)] ),
		LALRState( [LALRAction(6,LALRAction.Type.Shift,12),LALRAction(7,LALRAction.Type.Shift,13),LALRAction(0,LALRAction.Type.Reduce,0),LALRAction(3,LALRAction.Type.Reduce,0),LALRAction(5,LALRAction.Type.Reduce,0),LALRAction(8,LALRAction.Type.Reduce,0)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,3),LALRAction(3,LALRAction.Type.Reduce,3),LALRAction(5,LALRAction.Type.Reduce,3),LALRAction(6,LALRAction.Type.Reduce,3),LALRAction(7,LALRAction.Type.Reduce,3),LALRAction(8,LALRAction.Type.Reduce,3)] ),
		LALRState( [LALRAction(0,LALRAction.Type.Reduce,4),LALRAction(3,LALRAction.Type.Reduce,4),LALRAction(5,LALRAction.Type.Reduce,4),LALRAction(6,LALRAction.Type.Reduce,4),LALRAction(7,LALRAction.Type.Reduce,4),LALRAction(8,LALRAction.Type.Reduce,4)] ),
	];
	
	version(GoldieStaticLang)
	{
		private this()
		{
			super();
			name   = staticName;
			ver    = staticVer;
			author = staticAuthor;
			about  = staticAbout;
			caseSensitive = staticCaseSensitive;

			startSymbolIndex = staticStartSymbolIndex;
			initialDFAState  = staticInitialDFAState;
			initialLALRState = staticInitialLALRState;
			eofSymbolIndex   = staticEofSymbolIndex;
			errorSymbolIndex = staticErrorSymbolIndex;

			symbolTable  = staticSymbolTable;
			charSetTable = staticCharSetTable;
			ruleTable    = staticRuleTable;
			dfaTable     = staticDFATable;
			lalrTable    = staticLALRTable;

			symbolLookup = [
				"("                  : [Symbol("(",SymbolType.Terminal,4)],
				")"                  : [Symbol(")",SymbolType.Terminal,5)],
				"*"                  : [Symbol("*",SymbolType.Terminal,6)],
				"+"                  : [Symbol("+",SymbolType.Terminal,8)],
				"-"                  : [Symbol("-",SymbolType.Terminal,3)],
				"/"                  : [Symbol("/",SymbolType.Terminal,7)],
				"<Add Exp>"          : [Symbol("<Add Exp>",SymbolType.NonTerminal,10)],
				"<Mult Exp>"         : [Symbol("<Mult Exp>",SymbolType.NonTerminal,11)],
				"<Negate Exp>"       : [Symbol("<Negate Exp>",SymbolType.NonTerminal,12)],
				"<Value>"            : [Symbol("<Value>",SymbolType.NonTerminal,13)],
				"EOF"                : [Symbol("EOF",SymbolType.EOF,0)],
				"Error"              : [Symbol("Error",SymbolType.Error,1)],
				"Number"             : [Symbol("Number",SymbolType.Terminal,9)],
				"Whitespace"         : [Symbol("Whitespace",SymbolType.Whitespace,2)]
			];
		}

		public Lexer_calc lexCode(string source, string filename="")
		{
			return cast(Lexer_calc)lexCodeX(source, filename);
		}
		
		public Parser_calc parseTokens(Token[] tokens, string filename="", Lexer lexerUsed=null)
		{
			return cast(Parser_calc)parseTokensX(tokens, filename, lexerUsed);
		}

		public Lexer_calc lexFile(string filename)
		{
			return cast(Lexer_calc)lexFileX(filename);
		}

		public Parser_calc parseFile(string filename)
		{
			return cast(Parser_calc)parseFileX(filename);
		}

		public Parser_calc parseCode(string source, string filename="")
		{
			return cast(Parser_calc)parseCodeX(source, filename);
		}
	}

	public override Lexer lexCodeX(string source, string filename="")
	{
		lexer = new Lexer_calc();
		lexer.process(source, this, filename);
		return lexer;
	}
	
	public override Parser parseTokensX(Token[] tokens, string filename="", Lexer lexerUsed=null)
	{
		parser = new Parser_calc();
		parser.process(tokens, this, filename, lexerUsed);
		return parser;
	}

	
	
	public static bool staticIsSymbolNameValid(string name)
	{
		return staticLookupSymbol(name).length >= 1;
	}
	
	public static bool staticIsSymbolNameAmbiguous(string name)
	{
		return staticLookupSymbol(name).length > 1;
	}
	
	public static string[] staticUniqueSymbolNames()
	{
		version(GoldieStaticLang)
			return staticUniqueSymbolNameArray;
		else
			return symbolLookup.keys;
	}
	
	public static Symbol staticEofSymbol()
	{
		version(GoldieStaticLang)
			return staticSymbolTable[staticEofSymbolIndex];
		else
			return symbolTable[eofSymbolIndex];
	}
	
	public static Symbol staticErrorSymbol()
	{
		version(GoldieStaticLang)
			return staticSymbolTable[staticErrorSymbolIndex];
		else
			return symbolTable[errorSymbolIndex];
	}
	
	version(GoldieStaticLang)
	{
		public override bool isSymbolNameValid(string name)
		{
			return typeof(this).staticIsSymbolNameValid(name);
		}
		
		public override bool isSymbolNameAmbiguous(string name)
		{
			return typeof(this).staticIsSymbolNameAmbiguous(name);
		}
		
		public override string[] uniqueSymbolNames()
		{
			return typeof(this).staticUniqueSymbolNames();
		}
		
		public override Symbol eofSymbol()
		{
			return typeof(this).staticEofSymbol();
		}
		
		public override Symbol errorSymbol()
		{
			return typeof(this).staticErrorSymbol();
		}

		protected static Symbol[] staticLookupSymbol(string symName)
		{
			switch(symName)
			{
			case "(":                 return [Symbol("(",SymbolType.Terminal,4)];
			case ")":                 return [Symbol(")",SymbolType.Terminal,5)];
			case "*":                 return [Symbol("*",SymbolType.Terminal,6)];
			case "+":                 return [Symbol("+",SymbolType.Terminal,8)];
			case "-":                 return [Symbol("-",SymbolType.Terminal,3)];
			case "/":                 return [Symbol("/",SymbolType.Terminal,7)];
			case "<Add Exp>":         return [Symbol("<Add Exp>",SymbolType.NonTerminal,10)];
			case "<Mult Exp>":        return [Symbol("<Mult Exp>",SymbolType.NonTerminal,11)];
			case "<Negate Exp>":      return [Symbol("<Negate Exp>",SymbolType.NonTerminal,12)];
			case "<Value>":           return [Symbol("<Value>",SymbolType.NonTerminal,13)];
			case "EOF":               return [Symbol("EOF",SymbolType.EOF,0)];
			case "Error":             return [Symbol("Error",SymbolType.Error,1)];
			case "Number":            return [Symbol("Number",SymbolType.Terminal,9)];
			case "Whitespace":        return [Symbol("Whitespace",SymbolType.Whitespace,2)];
			default:
				return [];
			}
		}

		protected override Symbol[] lookupSymbol(string symName)
		{
			return typeof(this).staticLookupSymbol(symName);
		}
	}

	
}
