%include {
	#include "parser.h"
	
	// specify parser prefix
	#define yy sp
}

// used to set the tree
%extra_argument { CParser* obj }

%parse_failure {
	obj->setError(true);
	PRINT(cerr << "Parse error" << endl);
}

%syntax_error {
	obj->setError(true);
	PRINT(cerr << "Syntax error" << endl);
}

%token_type { TokenStruct }
%token_destructor {
	delete $$.string;
}
%token_prefix TOK_

datatype ::= struct(Struct). {
	obj->setRoot(Struct.node);
	obj->setFinished(true);
	
	PRINT(cerr << "struct (finished)" << endl);
}

/*
	struct XY {
		int a;
		int b;
	}
*/
struct(X) ::= STRUCT STRING(Sname) brace_content(Svalue) separator. {
	TreeNode* node = new TreeNode;
	
	node->type = Struct;
	node->name = *Sname.string;
	
	X.node = node;
	X.node->childList.append(Svalue.node);
	
	delete Sname.string;
	
	PRINT(cerr << "struct string brace_content" << endl);
}

/*
	struct {
		...
	}
*/
struct(X) ::= STRUCT brace_content(Svalue) separator. {
	TreeNode* node = new TreeNode;
	
	node->type = Struct;
	
	X.node = node;
	X.node->childList.append(Svalue.node);
	
	PRINT(cerr << "struct brace_content" << endl);
}

/*
	{
		...
	}
*/
brace_content(X) ::= BRACE_OPEN separator content(Value) BRACE_CLOSE. {
	X.node = Value.node;
}

content(X) ::= . {
	X.node = new TreeNode;
	X.node->type	= Null;
}

/*
	[4] 0
*/
content(X) ::= content(Root) bracket(Bracket) name(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Array;
	node->name	= *Bracket.string;
	node->value	= *Value.string;
	X.node = Root.node;
	X.node->childList.append(node);
		
	delete Bracket.string;
	delete Value.string;
	
	PRINT(cerr << "content bracket name separator" << endl);
}

/*
	[4] struct {
		...
	}
*/
content(X) ::= content(Root) bracket(Bracket) STRUCT brace_content(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= ArrayStruct;
	node->name	= *Bracket.string;
	X.node		= Root.node;
	X.node->childList.append(node);
	
	node->childList.append(Value.node);
	
	delete Bracket.string;
}

/*
	[3] struct XY {
		...
	}
*/
content(X) ::= content(Root) bracket(Bracket) STRUCT name(Sname) brace_content(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= ArrayStruct;
	node->name	= *Bracket.string;
	node->value	= *Sname.string;
	X.node		= Root.node;
	X.node->childList.append(node);

	node->childList.append(Value.node);
	
	delete Bracket.string;
	delete Sname.string;
	
	PRINT(cerr << "content bracket struct string brace_content sep" << endl);
}

/*
	[3] (null) = 0x20012
*/
content(X) ::= content(Root) bracket(Bracket) name EQUAL name(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Array;
	node->name	= *Bracket.string;
	node->value = *Value.string;
	X.node 		= Root.node;
	X.node->childList.append(node);
	
	delete Bracket.string;
	delete Value.string;
}

/*
	[4] XY {
	}
*/
content(X) ::= content(Root) bracket(Bracket) name(Sname) brace_content(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= ArrayStruct;
	node->name	= *Bracket.string;
	node->value	= *Sname.string;
	X.node = Root.node;
	X.node->childList.append(node);
	node->childList.append(Value.node);
	
	delete Bracket.string;
	delete Sname.string;
	
	PRINT(cerr << "content bracket name brace_content sep" << endl);
}

/*
	abc = {
		...
	}
*/
content(X) ::= content(Root) name(Sname) EQUAL brace_content(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->childList.append(Value.node);
	node->type	= Array;
	node->name	= *Sname.string;
	X.node		= Root.node;
	X.node->childList.append(node);
	
	delete Sname.string;
	
	PRINT(cerr << "content << name << equal brace_content sep" << endl);
}

/*
	abc = 5
*/
content(X) ::= content(Root) name(Name) EQUAL name(Value) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Scalar;
	node->name	= *Name.string;
	node->value	= *Value.string;
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Name.string;
	delete Value.string;
	
	PRINT(cerr << "content name equal name sep" << endl);
}

/*
	abc = 5 = '\005'
*/
content(X) ::= content(Root) name(Name) EQUAL name(Value) EQUAL name(Quote) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Scalar;
	node->name	= *Name.string;
	node->value	= *Value.string + " = " + *Quote.string;
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Name.string;
	delete Value.string;
	delete Quote.string;
	
	PRINT(cerr << "content name equal name equal string sep" << endl);
}

/*
	abc =
*/
content(X) ::= content(Root) name(Name) EQUAL separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Scalar;
	node->name	= *Name.string;
	node->value = "?";
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Name.string;
	
	PRINT(cerr << "content name equal sep" << endl);
}

/*
	abc = xyz_t {
		...
	}
*/
content(X) ::= content(Root) name(Sname) EQUAL name brace_content(Child) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Struct;
	node->name	= *Sname.string;
	node->childList.append(Child.node);
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Sname.string;
	
	PRINT(cerr << "content << name equal name brace_content sep" << endl);
}

/*
	abc = struct {
		...
	}
*/
content(X) ::= content(Root) name(Sname) EQUAL STRUCT brace_content(Child) separator. {
	TreeNode* node = new TreeNode;
	
	node->type = Struct;
	node->name = *Sname.string;
	node->childList.append(Child.node);
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Sname.string;
	
	PRINT(cerr << "content name equal struct brace_content sep" << endl);
}

/*
	abc = struct XY {
		...
	}
*/
content(X) ::= content(Root) name(Sname) EQUAL STRUCT STRING brace_content(Child) separator. {
	TreeNode* node = new TreeNode;
	
	node->type	= Struct;
	node->name	= *Sname.string;
	node->childList.append(Child.node);
	
	X.node = Root.node;
	X.node->childList.append(node);
	
	delete Sname.string;
	
	PRINT(cerr << "content name equal struct string brace_content sep" << endl);
}

/*
	Hello
*/
name(X) ::= STRING(A). {
	X.string = A.string;
	A.string = 0;
}

/*
	(Hello)
*/
name(X) ::= PAREN_OPEN STRING(A) PAREN_CLOSE.	{
	X.string = new QString;
	*X.string = QString("(") + *A.string + QString(")");
	delete A.string;
}

/* enum
	(XYZ=1)
*/
name(X) ::= PAREN_OPEN STRING(A) EQUAL STRING(B) PAREN_CLOSE. {
	X.string = new QString;
	*X.string = QString("(") + *A.string + "=" + *B.string + QString(")");
	delete A.string;
	delete B.string;
}

/*
	"Hello"
*/
name(X) ::= QUOTE STRING(A) QUOTE. {
	X.string = A.string;
	X.string->prepend("\"");
	X.string->append("\"");
	A.string = 0;
}

/*
	""
*/
name(X) ::= QUOTE QUOTE. {
	X.string = new QString("\"\"");
}

separator ::= SEP.
separator ::= separator SEP.

/*
	[4]
*/
bracket(X) ::= BRACKET_OPEN name(A) BRACKET_CLOSE. {
	X.string = new QString(*A.string);
	delete A.string;
}
