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

module goldie.base;

import tango.io.Stdout;
import tango.text.Regex;
import tango.text.Util;

import semitwist.util.all;

public enum GoldSymbolType
{
	NonTerminal  = 0,
	Terminal     = 1,
	Whitespace   = 2,
	EOF          = 3,
	CommentStart = 4,
	CommentEnd   = 5,
	CommentLine  = 6,
	Error        = 7,
}

public char[] goldSymbolTypeToString(GoldSymbolType type)
{
	static char[][GoldSymbolType] lookup;

	if(lookup.length == 0)
	{
		lookup =
		[
			GoldSymbolType.NonTerminal  : "NonTerminal"[],
			GoldSymbolType.Terminal     : "Terminal",
			GoldSymbolType.Whitespace   : "Whitespace",
			GoldSymbolType.EOF          : "EOF",
			GoldSymbolType.CommentStart : "CommentStart",
			GoldSymbolType.CommentEnd   : "CommentEnd",
			GoldSymbolType.CommentLine  : "CommentLine",
			GoldSymbolType.Error        : "Error"
		];
	}
	
	return lookup[type];
}

struct GoldCharSet
{
	wchar[] chars;

	char[] toString()
	{
		return "\n" ~ `GoldCharSet("{}")`.sformat(chars);
	}
}

struct GoldSymbol
{
	wchar[] name;
	GoldSymbolType type;
	int id;
	
	char[] toString()
	{
		return "\n" ~ `GoldSymbol("{}", {})`.sformat(name, type);
	}
}

struct GoldRule
{
	int nonTerminalIndex;
	int[] terminalIndicies;

	char[] toString()
	{
		return "\nGoldRule({}, {})".sformat(nonTerminalIndex, terminalIndicies);
	}
}

struct GoldDFAState
{
	bool accept;
	int acceptSymbolIndex;
	GoldDFAStateEdge[] edges;

	char[] toString()
	{
		return "\nGoldDFAState({}, {}, {})".sformat(accept, acceptSymbolIndex, edges);
	}
}

struct GoldDFAStateEdge
{
	int charSetIndex;
	int targetDFAStateIndex;

	char[] toString()
	{
		return "Edge({},{})".sformat(charSetIndex, targetDFAStateIndex);
	}
}

struct GoldLALRState
{
	GoldLALRAction[] actions;

	char[] toString()
	{
		return "\nGoldLALRState({})".sformat(actions);
	}
}

struct GoldLALRAction
{
	enum Type
	{
		Shift  = 1, // target: LALR State Index
		Reduce = 2, // target: Rule Index
		Goto   = 3, // target: LALR State Index
		Accept = 4  // target: unused
	}
	
	int symbolId;
	Type type;
	int target;

	char[] toString()
	{
		return "action({}, {}, {})".sformat(symbolId, type, target);
	}
}
