using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;
using ASTAttribute = ICSharpCode.NRefactory.Parser.AST.Attribute;
using Types = ICSharpCode.NRefactory.Parser.AST.ClassType;

COMPILER CS    /* AW 2002-12-30 renamed from CompilationUnit to CS  */

/*----------------------------- token sets -------------------------------*/
string        assemblyName     = null;
StringBuilder qualidentBuilder = new StringBuilder();

public string ContainingAssembly {
	set {
		assemblyName = value;
	}
}

Token t {
	[System.Diagnostics.DebuggerStepThrough]
	get {
		return lexer.Token;
	}
}

Token la {
	[System.Diagnostics.DebuggerStepThrough]
	get {
		return lexer.LookAhead;
	}
}

public void Error(string s)
{
	if (errDist >= minErrDist) {
		errors.Error(la.line, la.col, s);
	}
	errDist = 0;
}

public override Expression ParseExpression()
{
	lexer.NextToken();
	Expression expr;
	Expr(out expr);
	return expr;
}
// Begin ISTypeCast
bool IsTypeCast()
{
	if (la.kind != Tokens.OpenParenthesis) {
		return false;
	}
	if (IsSimpleTypeCast()) {
		return true;
	}
	return GuessTypeCast();
}

// "(" ( typeKW [ "[" {","} "]" | "*" ] | void  ( "[" {","} "]" | "*" ) ) ")"
// only for built-in types, all others use GuessTypeCast!
bool IsSimpleTypeCast ()
{
	// assert: la.kind == _lpar
	lexer.StartPeek();
	Token pt = lexer.Peek();
	
	if (!IsTypeKWForTypeCast(ref pt)) {
		return false;
	}
	return pt.kind == Tokens.CloseParenthesis;
}

/* !!! Proceeds from current peek position !!! */
bool IsTypeKWForTypeCast(ref Token pt)
{
	if (Tokens.TypeKW[pt.kind]) {
		pt = lexer.Peek();
		if (pt.kind == Tokens.Times || pt.kind == Tokens.OpenSquareBracket) {
			return IsPointerOrDims(ref pt);
		} else {
		  return true;
		}
	} else if (pt.kind == Tokens.Void) {
		pt = lexer.Peek();
		return IsPointerOrDims(ref pt);
	}
	return false;
}

/* !!! Proceeds from current peek position !!! */
bool IsTypeNameOrKWForTypeCast(ref Token pt)
{
	if (IsTypeKWForTypeCast(ref pt))
		return true;
	else
		return IsTypeNameForTypeCast(ref pt);
}

// TypeName = ident [ "::" ident ] {  "." ident } ["<" TypeNameOrKW { "," TypeNameOrKW } ">" ] PointerOrDims
/* !!! Proceeds from current peek position !!! */
bool IsTypeNameForTypeCast(ref Token pt)
{
	// ident
	if (pt.kind != Tokens.Identifier) {
		return false;
	}	
	pt = Peek();
	// "::" ident
	if (pt.kind == Tokens.DoubleColon) {
		pt = Peek();
		if (pt.kind != Tokens.Identifier) {
			return false;
		}
		pt = Peek();
	}
	// { "." ident }
	while (pt.kind == Tokens.Dot) {
		pt = Peek();
		if (pt.kind != Tokens.Identifier) {
			return false;
		}
		pt = Peek();
	}
	if (pt.kind == Tokens.LessThan) {
		do {
			pt = Peek();
			if (!IsTypeNameOrKWForTypeCast(ref pt)) {
				return false;
			}
		} while (pt.kind == Tokens.Comma);
		if (pt.kind != Tokens.GreaterThan) {
			return false;
		}
		pt = Peek();
	}
	if (pt.kind == Tokens.Times || pt.kind == Tokens.OpenSquareBracket) {
		return IsPointerOrDims(ref pt);
	}
	return true;
}

// "(" TypeName ")" castFollower
bool GuessTypeCast ()
{
	// assert: la.kind == _lpar
	StartPeek();
	Token pt = Peek();

	if (!IsTypeNameForTypeCast(ref pt)) {
		return false;
	}
	
	// ")"
	if (pt.kind != Tokens.CloseParenthesis) {
		return false;
	}
	// check successor
	pt = Peek();
	return Tokens.CastFollower[pt.kind] || (Tokens.TypeKW[pt.kind] && lexer.Peek().kind == Tokens.Dot);
}
// END IsTypeCast

/* Checks whether the next sequences of tokens is a qualident *
 * and returns the qualident string                           */
/* !!! Proceeds from current peek position !!! */
bool IsQualident(ref Token pt, out string qualident)
{
	if (pt.kind == Tokens.Identifier) {
		qualidentBuilder.Length = 0; qualidentBuilder.Append(pt.val);
		pt = Peek();
	while (pt.kind == Tokens.Dot || pt.kind == Tokens.DoubleColon) {
			pt = Peek();
			if (pt.kind != Tokens.Identifier) {
				qualident = String.Empty;
				return false;
			}
			qualidentBuilder.Append('.');
			qualidentBuilder.Append(pt.val);
			pt = Peek();
		}
		qualident = qualidentBuilder.ToString();
		return true;
	}
	qualident = String.Empty;
	return false;
}

/* Skips generic type extensions */
/* !!! Proceeds from current peek position !!! */

/* skip: { "*" | "[" { "," } "]" } */
/* !!! Proceeds from current peek position !!! */
bool IsPointerOrDims (ref Token pt)
{
	for (;;) {
		if (pt.kind == Tokens.OpenSquareBracket) {
			do pt = Peek();
			while (pt.kind == Tokens.Comma);
			if (pt.kind != Tokens.CloseSquareBracket) return false;
		} else if (pt.kind != Tokens.Times) break;
		pt = Peek();
	}
	return true;
}

/* Return the n-th token after the current lookahead token */
void StartPeek()
{
	lexer.StartPeek();
}

Token Peek()
{
	return lexer.Peek();
}

Token Peek (int n)
{
	lexer.StartPeek();
	Token x = la;
	while (n > 0) {
		x = lexer.Peek();
		n--;
	}
	return x;
}

/*-----------------------------------------------------------------*
 * Resolver routines to resolve LL(1) conflicts:                   *                                                  *
 * These resolution routine return a boolean value that indicates  *
 * whether the alternative at hand shall be choosen or not.        *
 * They are used in IF ( ... ) expressions.                        *       
 *-----------------------------------------------------------------*/

/* True, if ident is followed by "=" */
bool IdentAndAsgn ()
{
	return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.Assign;
}

bool IsAssignment () { return IdentAndAsgn(); }

/* True, if ident is followed by ",", "=", or ";" */
bool IdentAndCommaOrAsgnOrSColon () {
	int peek = Peek(1).kind;
	return la.kind == Tokens.Identifier && 
	       (peek == Tokens.Comma || peek == Tokens.Assign || peek == Tokens.Semicolon);
}
bool IsVarDecl () { return IdentAndCommaOrAsgnOrSColon(); }

/* True, if the comma is not a trailing one, *
 * like the last one in: a, b, c,            */
bool NotFinalComma () {
	int peek = Peek(1).kind;
	return la.kind == Tokens.Comma &&
	       peek != Tokens.CloseCurlyBrace && peek != Tokens.CloseSquareBracket;
}

/* True, if "void" is followed by "*" */
bool NotVoidPointer () {
	return la.kind == Tokens.Void && Peek(1).kind != Tokens.Times;
}

/* True, if "checked" or "unchecked" are followed by "{" */
bool UnCheckedAndLBrace () {
	return la.kind == Tokens.Checked || la.kind == Tokens.Unchecked &&
	       Peek(1).kind == Tokens.OpenCurlyBrace;
}

/* True, if "." is followed by an ident */
bool DotAndIdent () {
	return la.kind == Tokens.Dot && Peek(1).kind == Tokens.Identifier;
}

/* True, if ident is followed by ":" */
bool IdentAndColon () {
	return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.Colon;
}

bool IsLabel () { return IdentAndColon(); }

/* True, if ident is followed by "(" */
bool IdentAndLPar () {
	return la.kind == Tokens.Identifier && Peek(1).kind == Tokens.OpenParenthesis;
}

/* True, if "catch" is followed by "(" */
bool CatchAndLPar () {
	return la.kind == Tokens.Catch && Peek(1).kind == Tokens.OpenParenthesis;
}
bool IsTypedCatch () { return CatchAndLPar(); }

/* True, if "[" is followed by the ident "assembly" */
bool IsGlobalAttrTarget () {
	Token pt = Peek(1);
	return la.kind == Tokens.OpenSquareBracket && 
	       pt.kind == Tokens.Identifier && pt.val == "assembly";
}

/* True, if "[" is followed by "," or "]" */
bool LBrackAndCommaOrRBrack () {
	int peek = Peek(1).kind;
	return la.kind == Tokens.OpenSquareBracket &&
	       (peek == Tokens.Comma || peek == Tokens.CloseSquareBracket);
}

bool IsDims () { return LBrackAndCommaOrRBrack(); }

/* True, if "[" is followed by "," or "]" */
/* or if the current token is "*"         */
bool TimesOrLBrackAndCommaOrRBrack () {
	return la.kind == Tokens.Times || LBrackAndCommaOrRBrack();
}
bool IsPointerOrDims () { return TimesOrLBrackAndCommaOrRBrack(); }
bool IsPointer () { return la.kind == Tokens.Times; }


bool SkipGeneric(ref Token pt)
{
	if (pt.kind == Tokens.LessThan) {
		int braces = 1;
		while (braces != 0) {
			pt = Peek();
			if (pt.kind == Tokens.GreaterThan) {
				--braces;
			} else if (pt.kind == Tokens.LessThan) {
				++braces;
			} else if (pt.kind == Tokens.Semicolon || pt.kind == Tokens.OpenCurlyBrace || pt.kind == Tokens.CloseCurlyBrace || pt.kind == Tokens.EOF) {
				return false;
			}
		}
		pt = Peek();
	}
	return true;
}
bool SkipQuestionMark(ref Token pt)
{
	if (pt.kind == Tokens.Question) {
		pt = Peek();
	}
	return true;
}

/* True, if lookahead is a primitive type keyword, or */
/* if it is a type declaration followed by an ident   */
bool IsLocalVarDecl () {
	if (IsYieldStatement()) {
		return false;
	}
	if ((Tokens.TypeKW[la.kind] && Peek(1).kind != Tokens.Dot) || la.kind == Tokens.Void) {
		return true;
	}
	
	StartPeek();
	Token pt = la ;
	string ignore;
	if (!IsQualident(ref pt, out ignore)) return false;
	if (!SkipGeneric(ref pt)) return false;
	while (pt.kind == Tokens.Dot) {
		pt = Peek();
		if (!IsQualident(ref pt, out ignore)) return false;
		if (!SkipGeneric(ref pt)) return false;
	}
	return SkipQuestionMark(ref pt) && IsPointerOrDims(ref pt) && pt.kind == Tokens.Identifier;
}

/* True if lookahead is type parameters (<...>) followed by the specified token */
bool IsGenericFollowedBy(int token)
{
	Token t = la;
	if (t.kind != Tokens.LessThan) return false;
	StartPeek();
	return SkipGeneric(ref t) && t.kind == token;
}

bool IsExplicitInterfaceImplementation()
{
	StartPeek();
	Token pt = la;
	pt = Peek();
	if (pt.kind == Tokens.Dot || pt.kind == Tokens.DoubleColon)
		return true;
	if (pt.kind == Tokens.LessThan) {
		if (SkipGeneric(ref pt))
			return pt.kind == Tokens.Dot;
	}
	return false;
}

/* True, if lookahead ident is "where" */
bool IdentIsWhere () {
	return la.kind == Tokens.Identifier && la.val == "where";
}

/* True, if lookahead ident is "get" */
bool IdentIsGet () {
	return la.kind == Tokens.Identifier && la.val == "get";
}

/* True, if lookahead ident is "set" */
bool IdentIsSet () {
	return la.kind == Tokens.Identifier && la.val == "set";
}

/* True, if lookahead ident is "add" */
bool IdentIsAdd () {
	return la.kind == Tokens.Identifier && la.val == "add";
}

/* True, if lookahead ident is "remove" */
bool IdentIsRemove () {
	return la.kind == Tokens.Identifier && la.val == "remove";
}

bool IsNotYieldStatement () {
	return !IsYieldStatement();
}
/* True, if lookahead ident is "yield" and than follows a break or return */
bool IsYieldStatement () {
	return la.kind == Tokens.Identifier && la.val == "yield" && (Peek(1).kind == Tokens.Return || Peek(1).kind == Tokens.Break);
}

/* True, if lookahead is a local attribute target specifier, *
 * i.e. one of "event", "return", "field", "method",         *
 *             "module", "param", "property", or "type"      */
bool IsLocalAttrTarget () {
	int cur = la.kind;
	string val = la.val;

	return (cur == Tokens.Event || cur == Tokens.Return ||
	        (cur == Tokens.Identifier &&
	         (val == "field" || val == "method"   || val == "module" ||
	          val == "param" || val == "property" || val == "type"))) &&
	       Peek(1).kind == Tokens.Colon;
}

bool IsShiftRight() 
{
	Token next = Peek(1);
	// TODO : Add col test (seems not to work, lexer bug...) :  && la.col == next.col - 1
	return (la.kind == Tokens.GreaterThan && next.kind == Tokens.GreaterThan);
}

bool IsTypeReferenceExpression(Expression expr)
{
	if (expr is TypeReferenceExpression) return ((TypeReferenceExpression)expr).TypeReference.GenericTypes.Count == 0;
	while (expr is FieldReferenceExpression) {
		expr = ((FieldReferenceExpression)expr).TargetObject;
		if (expr is TypeReferenceExpression) return true;
	}
	return expr is IdentifierExpression;
}

TypeReferenceExpression GetTypeReferenceExpression(Expression expr, List<TypeReference> genericTypes)
{
	TypeReferenceExpression	tre = expr as TypeReferenceExpression;
	if (tre != null) {
		return new TypeReferenceExpression(new TypeReference(tre.TypeReference.Type, tre.TypeReference.PointerNestingLevel, tre.TypeReference.RankSpecifier, genericTypes));
	}
	StringBuilder b = new StringBuilder();
	if (!WriteFullTypeName(b, expr)) {
		// there is some TypeReferenceExpression hidden in the expression
		while (expr is FieldReferenceExpression) {
			expr = ((FieldReferenceExpression)expr).TargetObject;
		}
		tre = expr as TypeReferenceExpression;
		if (tre != null) {
			TypeReference typeRef = tre.TypeReference;
			if (typeRef.GenericTypes.Count == 0) {
				typeRef = typeRef.Clone();
				typeRef.Type += "." + b.ToString();
				typeRef.GenericTypes.AddRange(genericTypes);
			} else {
				typeRef = new InnerClassTypeReference(typeRef, b.ToString(), genericTypes);
			}
			return new TypeReferenceExpression(typeRef);
		}
	}
	return new TypeReferenceExpression(new TypeReference(b.ToString(), 0, null, genericTypes));
}

/* Writes the type name represented through the expression into the string builder. */
/* Returns true when the expression was converted successfully, returns false when */
/* There was an unknown expression (e.g. TypeReferenceExpression) in it */
bool WriteFullTypeName(StringBuilder b, Expression expr)
{
	FieldReferenceExpression fre = expr as FieldReferenceExpression;
	if (fre != null) {
		bool result = WriteFullTypeName(b, fre.TargetObject);
		if (b.Length > 0) b.Append('.');
		b.Append(fre.FieldName);
		return result;
	} else if (expr is IdentifierExpression) {
		b.Append(((IdentifierExpression)expr).Identifier);
		return true;
	} else {
		return false;
	}
}

/*------------------------------------------------------------------------*
 *----- LEXER TOKEN LIST  ------------------------------------------------*
 *------------------------------------------------------------------------*/

/* START AUTOGENERATED TOKENS SECTION */
TOKENS
	/* ----- terminal classes ----- */
	/* EOF is 0 */
	ident
	Literal

	/* ----- special character ----- */
	"="
	"+"
	"-"
	"*"
	"/"
	"%"
	":"
	"::"
	";"
	"?"
	"??"
	","
	"."
	"{"
	"}"
	"["
	"]"
	"("
	")"
	">"
	"<"
	"!"
	"&&"
	"||"
	"~"
	"&"
	"|"
	"^"
	"++"
	"--"
	"=="
	"!="
	">="
	"<="
	"<<"
	"+="
	"-="
	"*="
	"/="
	"%="
	"&="
	"|="
	"^="
	"<<="
	"->"

	/* ----- keywords ----- */
	"abstract"
	"as"
	"base"
	"bool"
	"break"
	"byte"
	"case"
	"catch"
	"char"
	"checked"
	"class"
	"const"
	"continue"
	"decimal"
	"default"
	"delegate"
	"do"
	"double"
	"else"
	"enum"
	"event"
	"explicit"
	"extern"
	"false"
	"finally"
	"fixed"
	"float"
	"for"
	"foreach"
	"goto"
	"if"
	"implicit"
	"in"
	"int"
	"interface"
	"internal"
	"is"
	"lock"
	"long"
	"namespace"
	"new"
	"null"
	"object"
	"operator"
	"out"
	"override"
	"params"
	"private"
	"protected"
	"public"
	"readonly"
	"ref"
	"return"
	"sbyte"
	"sealed"
	"short"
	"sizeof"
	"stackalloc"
	"static"
	"string"
	"struct"
	"switch"
	"this"
	"throw"
	"true"
	"try"
	"typeof"
	"uint"
	"ulong"
	"unchecked"
	"unsafe"
	"ushort"
	"using"
	"virtual"
	"void"
	"volatile"
	"while"
/* END AUTOGENERATED TOKENS SECTION */

/*------------------------------------------------------------------------*
 *----- PARSER -----------------------------------------------------------*
 *------------------------------------------------------------------------*/

PRODUCTIONS

/*--- compilation unit: */
CS
(. lexer.NextToken(); /* get the first token */
   compilationUnit = new CompilationUnit(); .)
=
	{ UsingDirective }
	{ IF (IsGlobalAttrTarget()) GlobalAttributeSection }
	{ NamespaceMemberDecl }
	EOF
.

UsingDirective
(.
	string qualident = null; TypeReference aliasedType = null;
.)
=
	"using"                     (. Point startPos = t.Location; .)
	Qualident<out qualident>
	[ "=" NonArrayType<out aliasedType> ]
	";"                         (. 
	                               if (qualident != null && qualident.Length > 0) {
	                                 INode node;
	                                 if (aliasedType != null) {
	                                     node = new UsingDeclaration(qualident, aliasedType);
	                                 } else {
	                                     node = new UsingDeclaration(qualident);
	                                 }
	                                 node.StartLocation = startPos;
	                                 node.EndLocation   = t.EndLocation;
	                                 compilationUnit.AddChild(node);
	                               }
	                            .)
.

GlobalAttributeSection
=
	"[" (. Point startPos = t.Location; .) ident
	                            (. if (t.val != "assembly") Error("global attribute target specifier (\"assembly\") expected");
	                               string attributeTarget = t.val;
	                               List<ASTAttribute> attributes = new List<ASTAttribute>();
	                               ASTAttribute attribute;
	                            .)
	":" Attribute<out attribute> (. attributes.Add(attribute); .)
	{ IF (NotFinalComma()) "," Attribute<out attribute> (. attributes.Add(attribute); .)}
	[ "," ]
	"]"                         (. AttributeSection section = new AttributeSection(attributeTarget, attributes);
	                               section.StartLocation = startPos;
	                               section.EndLocation = t.EndLocation;
	                               compilationUnit.AddChild(section);
	                            .)
.

Attribute<out ASTAttribute attribute>
(. string qualident;
   string alias = null;
.)
=
	[ IF (la.kind == Tokens.Identifier && Peek(1).kind == Tokens.DoubleColon)
		ident (. alias = t.val; .)
		"::"
	]
	Qualident<out qualident> 
	(. List<Expression> positional = new List<Expression>();
	   List<NamedArgumentExpression> named = new List<NamedArgumentExpression>();
	   string name = (alias != null && alias != "global") ? alias + "." + qualident : qualident;
	.)
	[ AttributeArguments<positional, named> ] (. attribute  = new ICSharpCode.NRefactory.Parser.AST.Attribute(name, positional, named);.)
.

AttributeArguments<List<Expression> positional, List<NamedArgumentExpression> named>
(.
	bool nameFound = false;
	string name = "";
	Expression expr;
.)
=
	"("
	[
		[
			IF (IsAssignment())          (. nameFound = true; .)
			ident                        (. name = t.val; .)
			"="
		] Expr<out expr>                 (. if (expr != null) {if(name == "") positional.Add(expr);
		                                    else { named.Add(new NamedArgumentExpression(name, expr)); name = ""; }
		                                    }
		                                 .)
		
		{
			","
				(
					IF (IsAssignment())    (. nameFound = true; .)
					ident                      (. name = t.val; .)
					"="
					| /*Empty*/                (. if (nameFound) Error("no positional argument after named argument"); .)
				) Expr<out expr>           (. if (expr != null) { if(name == "") positional.Add(expr);
				                              else { named.Add(new NamedArgumentExpression(name, expr)); name = ""; }
				                              }
				                           .)
		}
	]
	")"
.

AttributeSection<out AttributeSection section>
(.
	string attributeTarget = "";
	List<ASTAttribute> attributes = new List<ASTAttribute>();
	ASTAttribute attribute;
	
.)
=
	"[" (. Point startPos = t.Location; .) /*--- attribute target specifier: */
	[ IF (IsLocalAttrTarget())
		( "event"                       (. attributeTarget = "event";.)
		| "return"                      (. attributeTarget = "return";.)
		| ident                         (. if (t.val != "field"    || t.val != "method" ||
		                                      t.val != "module"   || t.val != "param"  ||
		                                      t.val != "property" || t.val != "type")
		                                    Error("attribute target specifier (event, return, field," +
		                                          "method, module, param, property, or type) expected");
		                                   attributeTarget = t.val;
		                                .)
		) ":" 
	]
	/*--- attribute list: */
	Attribute<out attribute>            (. attributes.Add(attribute); .)
	{ IF (NotFinalComma()) "," Attribute<out attribute> (. attributes.Add(attribute); .)}
	[ "," ]
	"]"                         (. section = new AttributeSection(attributeTarget, attributes);
	                               section.StartLocation = startPos;
	                               section.EndLocation = t.EndLocation;
	                            .)
.

NamespaceMemberDecl
(.
	AttributeSection section;
	List<AttributeSection> attributes = new List<AttributeSection>();
	Modifiers m = new Modifiers();
	string qualident;
.)
= /*--- namespace declaration: */
	"namespace"                  (. Point startPos = t.Location; .)
	Qualident<out qualident>     (. INode node =  new NamespaceDeclaration(qualident);
	                                node.StartLocation = startPos;
	                                compilationUnit.AddChild(node);
	                                compilationUnit.BlockStart(node);
	                              .)
	"{"
	{ UsingDirective }
	{ NamespaceMemberDecl }
	"}"
	[ ";" ]                       (. node.EndLocation   = t.EndLocation;
	                                 compilationUnit.BlockEnd();
	                              .)
	/*--- type declaration: */
	| { AttributeSection<out section> (. attributes.Add(section); .) }
	  { TypeModifier<m> }
	  TypeDecl<m, attributes>
.

TypeDecl<Modifiers m, List<AttributeSection> attributes>
(.
	TypeReference type;
	List<TypeReference> names;
	List<ParameterDeclarationExpression> p = new List<ParameterDeclarationExpression>();
	string name;
	List<TemplateDefinition> templates;
.)
= /*--- class declaration: */      (. m.Check(Modifier.Classes); .)
	"class"                        (. TypeDeclaration newType = new TypeDeclaration(m.Modifier, attributes);
	                                  templates = newType.Templates;
	                                  compilationUnit.AddChild(newType);
	                                  compilationUnit.BlockStart(newType);
	                                  newType.StartLocation = m.GetDeclarationLocation(t.Location);
	                                  
	                                  newType.Type = Types.Class;
	                                .)
	ident                           (. newType.Name = t.val; .)
	
	/* .NET 2.0 */
	[ TypeParameterList<templates> ]
	
	[ ClassBase<out names>          (. newType.BaseTypes = names; .) ]
	
	/* .NET 2.0 */
	{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
	
	ClassBody
	[ ";" ]                         (. newType.EndLocation = t.Location; 
	                                   compilationUnit.BlockEnd();
	                                .)
	| /*--- struct declaration: */  (. m.Check(Modifier.StructsInterfacesEnumsDelegates); .)
	( "struct"                      (. TypeDeclaration newType = new TypeDeclaration(m.Modifier, attributes);
	                                   templates = newType.Templates;
	                                   newType.StartLocation = m.GetDeclarationLocation(t.Location);
	                                   compilationUnit.AddChild(newType);
	                                   compilationUnit.BlockStart(newType);
	                                   newType.Type = Types.Struct; 
	                                 .)
	ident                            (. newType.Name = t.val; .)
	
	/* .NET 2.0 */
	[ TypeParameterList<templates> ]
	
	[ StructInterfaces<out names>    (. newType.BaseTypes = names; .) ]
	
	/* .NET 2.0 */
	{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
	
	
	StructBody
	[ ";" ]                          (. newType.EndLocation = t.Location; 
	                                    compilationUnit.BlockEnd();
	                                 .)
	| /*--- interface declaration: */ 
	"interface"                      (. TypeDeclaration newType = new TypeDeclaration(m.Modifier, attributes);
	                                    templates = newType.Templates;
	                                    compilationUnit.AddChild(newType);
	                                    compilationUnit.BlockStart(newType);
	                                    newType.StartLocation = m.GetDeclarationLocation(t.Location);
	                                    newType.Type = Types.Interface;
	                                  .)
	ident                            (. newType.Name = t.val; .)
	
	/* .NET 2.0 */
	[ TypeParameterList<templates> ]
	
	[ InterfaceBase<out names>       (. newType.BaseTypes = names; .) ]
	
	/* .NET 2.0 */
	{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
	
	InterfaceBody
	[ ";" ]                          (. newType.EndLocation = t.Location; 
	                                    compilationUnit.BlockEnd();
	                                 .)
	| /*--- enumeration declaration: */
	"enum"                           (. TypeDeclaration newType = new TypeDeclaration(m.Modifier, attributes);
	                                    compilationUnit.AddChild(newType);
	                                    compilationUnit.BlockStart(newType);
	                                    newType.StartLocation = m.GetDeclarationLocation(t.Location);
	                                    newType.Type = Types.Enum;
	                                  .)
	ident                            (. newType.Name = t.val; .)
	[ ":" IntegralType<out name>     (. newType.BaseTypes.Add(new TypeReference(name)); .)
	]
	EnumBody 
	[ ";" ]                          (. newType.EndLocation = t.Location; 
	                                    compilationUnit.BlockEnd();
	                                 .)
	| /*--- delegate declaration: */
	"delegate"                       (. DelegateDeclaration delegateDeclr = new DelegateDeclaration(m.Modifier, attributes);
	                                    templates = delegateDeclr.Templates;
	                                    delegateDeclr.StartLocation = m.GetDeclarationLocation(t.Location);
	                                 .)
	( IF (NotVoidPointer()) "void"   (. delegateDeclr.ReturnType = new TypeReference("void", 0, null); .)
		| Type<out type>             (. delegateDeclr.ReturnType = type; .)
	)
	ident                            (. delegateDeclr.Name = t.val; .)
	
	/* .NET 2.0 */
	[ TypeParameterList<templates> ]
	
	"(" [ FormalParameterList<p> (. delegateDeclr.Parameters = p; .)
	] ")"
	
	/* .NET 2.0 */
	{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
	
	";"                              (. delegateDeclr.EndLocation = t.Location;
	                                    compilationUnit.AddChild(delegateDeclr);
	                                 .)
	)
.

Qualident<out string qualident>
=
	ident                              (. qualidentBuilder.Length = 0; qualidentBuilder.Append(t.val); .)
	{ IF (DotAndIdent()) "." ident     (. qualidentBuilder.Append('.');
	                                      qualidentBuilder.Append(t.val); 
	                                    .)
	} (. qualident = qualidentBuilder.ToString(); .)
.

ClassBase<out List<TypeReference> names>
(.
	TypeReference typeRef;
	names = new List<TypeReference>();
.)
=
	":" ClassType<out typeRef, false>  (. if (typeRef != null) { names.Add(typeRef); } .)
	{ "," TypeName<out typeRef, false> (. if (typeRef != null) { names.Add(typeRef); } .) }
.

ClassBody
(. AttributeSection section; .)
=
	"{"
	{                                  (.List<AttributeSection> attributes = new List<AttributeSection>();
		                                 Modifiers m = new Modifiers();
		                               .)
		{ AttributeSection<out section> (. attributes.Add(section); .) }
		{ MemberModifier<m> } 
		ClassMemberDecl<m, attributes> 
	}
	"}"
.

StructInterfaces<out List<TypeReference> names>
(.
	TypeReference typeRef;
	names = new List<TypeReference>();
.)
=
	":" TypeName<out typeRef, false>   (. if (typeRef != null) { names.Add(typeRef); } .)
	{ "," TypeName<out typeRef, false> (. if (typeRef != null) { names.Add(typeRef); } .) }
.

StructBody
(. AttributeSection section; .)
=
	"{" 
	{                                    (.List<AttributeSection> attributes = new List<AttributeSection>();
		                                   Modifiers m = new Modifiers();
		                                 .)
		{ AttributeSection<out section>  (. attributes.Add(section); .) }
		{ MemberModifier<m> } 
		StructMemberDecl<m, attributes> 
	}
	"}" 
.

InterfaceBase<out List<TypeReference> names>
(.
	TypeReference typeRef;
	names = new List<TypeReference>();
.)
=
	":" TypeName<out typeRef, false>   (. if (typeRef != null) { names.Add(typeRef); } .)
	{ "," TypeName<out typeRef, false> (. if (typeRef != null) { names.Add(typeRef); } .) }
.

InterfaceBody
= "{" { InterfaceMemberDecl } "}" .

EnumBody                                 (. FieldDeclaration f; .)
=
	"{" [ EnumMemberDecl<out f>          (. compilationUnit.AddChild(f); .)
	{ IF (NotFinalComma()) "," EnumMemberDecl<out f> (. compilationUnit.AddChild(f); .)
	}
	[","] ] "}"
.

Type<out TypeReference type>
=
	TypeWithRestriction<out type, true, false>
.

TypeWithRestriction<out TypeReference type, bool allowNullable, bool canBeUnbound>
(.
	string name;
	int pointer = 0;
	type = null;
.)
=
	( ClassType<out type, canBeUnbound>
	| SimpleType<out name> (. type = new TypeReference(name); .)
	| "void" "*"                         (. pointer = 1; type = new TypeReference("void"); .)
	)                                    (. List<int> r = new List<int>(); .)
	
	[ IF (allowNullable && la.kind == Tokens.Question) NullableQuestionMark<ref type> ]
	
	{ IF (IsPointerOrDims())             (. int i = 0; .)
		( "*"                            (. ++pointer; .)
		| "[" { "," (. ++i; .) } "]"     (. r.Add(i); .)
		)
	}
	(. if (type != null) {
		type.RankSpecifier = r.ToArray();
		type.PointerNestingLevel = pointer;
	   }
	.)
.


NonArrayType<out TypeReference type>
(.
	string name;
	int pointer = 0;
	type = null;
.)
=
	( ClassType<out type, false>
	| SimpleType<out name> (. type = new TypeReference(name); .)
	| "void" "*"           (. pointer = 1; type = new TypeReference("void"); .)
	)
	
	[ NullableQuestionMark<ref type> ]
	
	{ IF (IsPointer())
		"*" (. ++pointer; .)
	}
	(. if (type != null) { type.PointerNestingLevel = pointer; } .)
.

SimpleType<out string name>
(. name = String.Empty; .)
=
	IntegralType<out name> 
	| "float"   (. name = "float"; .)
	| "double"  (. name = "double"; .)
	| "decimal" (. name = "decimal"; .)
	| "bool"    (. name = "bool"; .)
.


FormalParameterList<List<ParameterDeclarationExpression> parameter>
(.
	
	ParameterDeclarationExpression p;
	AttributeSection section;
	List<AttributeSection> attributes = new List<AttributeSection>();
.)
=
	{ AttributeSection<out section> (.attributes.Add(section); .) }
	(
		FixedParameter<out p> (. bool paramsFound = false;
		                         p.Attributes = attributes;
		                         parameter.Add(p);
		                      .)
		{
			","                              (. attributes = new List<AttributeSection>(); if (paramsFound) Error("params array must be at end of parameter list"); .)
			{ AttributeSection<out section> (.attributes.Add(section); .) }
			(
				FixedParameter<out p>        (. p.Attributes = attributes; parameter.Add(p); .)
				| ParameterArray<out p>      (. paramsFound = true; p.Attributes = attributes; parameter.Add(p); .)
			)
		}
		| ParameterArray<out p>              (. p.Attributes = attributes; parameter.Add(p); .)
	)
.

FixedParameter<out ParameterDeclarationExpression p>
(.
	TypeReference type;
	ParamModifier mod = ParamModifier.In;
	System.Drawing.Point start = t.Location;
.)
=
	[
		"ref"    (. mod = ParamModifier.Ref; .)
		| "out"  (. mod = ParamModifier.Out; .)
	]
	Type<out type> ident (. p = new ParameterDeclarationExpression(type, t.val, mod); p.StartLocation = start; p.EndLocation = t.Location; .)
.

ParameterArray<out ParameterDeclarationExpression p>
(. TypeReference type; .)
=
	"params" Type<out type> ident (. p = new ParameterDeclarationExpression(type, t.val, ParamModifier.Params); .)
. 

AccessorModifiers<out Modifiers m>
(. m = new Modifiers(); .)
=
	"private"          (. m.Add(Modifier.Private, t.Location); .)
	| "protected"      (. m.Add(Modifier.Protected, t.Location); .)
	  ["internal"      (. m.Add(Modifier.Internal, t.Location); .)]
	| "internal"       (. m.Add(Modifier.Internal, t.Location); .)
	  ["protected"     (. m.Add(Modifier.Protected, t.Location); .)]
.

TypeModifier<Modifiers m>
=
	"new"                              (. m.Add(Modifier.New, t.Location); .)
	| "public"                         (. m.Add(Modifier.Public, t.Location); .)
	| "protected"                      (. m.Add(Modifier.Protected, t.Location); .)
	| "internal"                       (. m.Add(Modifier.Internal, t.Location); .)
	| "private"                        (. m.Add(Modifier.Private, t.Location); .)
	| "unsafe"                         (. m.Add(Modifier.Unsafe, t.Location); .)
	| "abstract"                       (. m.Add(Modifier.Abstract, t.Location); .)
	| "sealed"                         (. m.Add(Modifier.Sealed, t.Location); .)
	| "static"                         (. m.Add(Modifier.Static, t.Location); .)
	| ident                            (. if (t.val == "partial") { m.Add(Modifier.Partial, t.Location); } .)
.

ClassType<out TypeReference typeRef, bool canBeUnbound>
(. TypeReference r; typeRef = null; .)
=
	TypeName<out r, canBeUnbound> (. typeRef = r; .)
	| "object"                    (. typeRef = new TypeReference("object"); .)
	| "string"                    (. typeRef = new TypeReference("string"); .)
.

IntegralType<out string name>          (. name = ""; .)
=
	"sbyte"                            (. name = "sbyte"; .)
	| "byte"                           (. name = "byte"; .)
	| "short"                          (. name = "short"; .)
	| "ushort"                         (. name = "ushort"; .)
	| "int"                            (. name = "int"; .)
	| "uint"                           (. name = "uint"; .)
	| "long"                           (. name = "long"; .)
	| "ulong"                          (. name = "ulong"; .)
	| "char"                           (. name = "char"; .)
.

MemberModifier<Modifiers m>
=
	"abstract"                         (. m.Add(Modifier.Abstract, t.Location); .)
	| "extern"                         (. m.Add(Modifier.Extern, t.Location); .)
	| "internal"                       (. m.Add(Modifier.Internal, t.Location); .)
	| "new"                            (. m.Add(Modifier.New, t.Location); .)
	| "override"                       (. m.Add(Modifier.Override, t.Location); .)
	| "private"                        (. m.Add(Modifier.Private, t.Location); .)
	| "protected"                      (. m.Add(Modifier.Protected, t.Location); .)
	| "public"                         (. m.Add(Modifier.Public, t.Location); .)
	| "readonly"                       (. m.Add(Modifier.ReadOnly, t.Location); .)
	| "sealed"                         (. m.Add(Modifier.Sealed, t.Location); .)
	| "static"                         (. m.Add(Modifier.Static, t.Location); .)
	| "unsafe"                         (. m.Add(Modifier.Unsafe, t.Location); .)
	| "virtual"                        (. m.Add(Modifier.Virtual, t.Location); .)
	| "volatile"                       (. m.Add(Modifier.Volatile, t.Location); .)
.

StructMemberDecl<Modifiers m, List<AttributeSection> attributes>
(.
	string qualident = null;
	TypeReference type;
	Expression expr;
	List<ParameterDeclarationExpression> p = new List<ParameterDeclarationExpression>();
	Statement stmt = null;
	List<VariableDeclaration> variableDeclarators = new List<VariableDeclaration>();
	List<TemplateDefinition> templates = new List<TemplateDefinition>();
	TypeReference explicitInterface = null;
.)
=
	/*--- constant declaration: */         (. m.Check(Modifier.Constants); .)
	"const"                                (.Point startPos = t.Location; .)
	Type<out type> ident                   (. FieldDeclaration fd = new FieldDeclaration(attributes, type, m.Modifier | Modifier.Const);
	                                          fd.StartLocation = m.GetDeclarationLocation(startPos);
	                                          VariableDeclaration f = new VariableDeclaration(t.val);
	                                          fd.Fields.Add(f);
	                                       .)
	"=" Expr<out expr>                     (. f.Initializer = expr; .)
	{ "," ident                            (. f = new VariableDeclaration(t.val);
	                                          fd.Fields.Add(f);
	                                       .)
		"=" Expr<out expr>                 (. f.Initializer = expr; .)
	} ";"                                  (. fd.EndLocation = t.EndLocation; compilationUnit.AddChild(fd); .)
	
	/*--- void method (procedure) declaration: */
	| IF (NotVoidPointer())                (. m.Check(Modifier.PropertysEventsMethods); .)
	"void"                                 (. Point startPos = t.Location; .)
	( IF (IsExplicitInterfaceImplementation())
		TypeName<out explicitInterface, false>
		(.if (la.kind != Tokens.Dot || Peek(1).kind != Tokens.This) {
			qualident = TypeReference.StripLastIdentifierFromType(ref explicitInterface);
		  } .)
	|	ident (. qualident = t.val; .)
	)
	/* .NET 2.0 */
	[ TypeParameterList<templates> ]
	
	"("
	[ FormalParameterList<p> ] ")"
	(.	MethodDeclaration methodDeclaration = new MethodDeclaration(qualident,
		                                                            m.Modifier,
		                                                            new TypeReference("void"),
		                                                            p,
		                                                            attributes);
		methodDeclaration.StartLocation = m.GetDeclarationLocation(startPos);
		methodDeclaration.EndLocation   = t.EndLocation;
		methodDeclaration.Templates = templates;
		if (explicitInterface != null)
		methodDeclaration.InterfaceImplementations.Add(new InterfaceImplementation(explicitInterface, qualident));
		compilationUnit.AddChild(methodDeclaration);
		compilationUnit.BlockStart(methodDeclaration);
	.)
		
	/* .NET 2.0 */
	{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
	
	( Block<out stmt> | ";" )              (. compilationUnit.BlockEnd();
	                                          methodDeclaration.Body  = (BlockStatement)stmt;
	                                       .)
	
	| /*--- event declaration: */   (. m.Check(Modifier.PropertysEventsMethods); .)
		"event"                     (. EventDeclaration eventDecl = new EventDeclaration(m.Modifier, attributes);
		                               eventDecl.StartLocation = t.Location;
		                               compilationUnit.AddChild(eventDecl);
		                               compilationUnit.BlockStart(eventDecl);
		                               EventAddRegion addBlock = null;
		                               EventRemoveRegion removeBlock = null;
		                            .)
		Type<out type>        (. eventDecl.TypeReference = type; .)
		( IF (IsExplicitInterfaceImplementation())
			TypeName<out explicitInterface, false>
			(. qualident = TypeReference.StripLastIdentifierFromType(ref explicitInterface); .)
			(. eventDecl.InterfaceImplementations.Add(new InterfaceImplementation(explicitInterface, qualident)); .)
			
		|	ident (. qualident = t.val; .)
		)
		(. eventDecl.Name = qualident; eventDecl.EndLocation = t.EndLocation; .)
		[	"{" (. eventDecl.BodyStart = t.Location; .)
			EventAccessorDecls<out addBlock, out removeBlock> 
			"}" (. eventDecl.BodyEnd   = t.EndLocation; .)
		]
		[ ";" ]
		(. compilationUnit.BlockEnd();
		   eventDecl.AddRegion = addBlock;
		   eventDecl.RemoveRegion = removeBlock;
		.)
	
	/*--- constructor or static contructor declaration: */
	| IF (IdentAndLPar())                  (. m.Check(Modifier.Constructors | Modifier.StaticConstructors); .)
	ident (. string name = t.val; Point startPos = t.Location; .) "(" [  (. m.Check(Modifier.Constructors); .)
	FormalParameterList<p>
	]
	")" (.ConstructorInitializer init = null;  .)
	[                                      (. m.Check(Modifier.Constructors); .)
		ConstructorInitializer<out init>
	] (. 
	     ConstructorDeclaration cd = new ConstructorDeclaration(name, m.Modifier, p, init, attributes); 
	     cd.StartLocation = startPos;
	     cd.EndLocation   = t.EndLocation;
	  .)
	
	( Block<out stmt> | ";" ) (. cd.Body = (BlockStatement)stmt; compilationUnit.AddChild(cd); .)
	
	/*--- conversion operator declaration: */
	|                                      (. m.Check(Modifier.Operators);
	                                          if (m.isNone) Error("at least one modifier must be set"); 
	                                          bool isImplicit = true;
	                                          Point startPos = Point.Empty;
	                                       .)
	( "implicit" (. startPos = t.Location; .) | "explicit" (. isImplicit = false; startPos = t.Location; .) ) 
	"operator" Type<out type> (. TypeReference operatorType = type; .) 
	"(" Type<out type> ident (. string varName = t.val; .) ")"
	(. Point endPos = t.Location; .)
	( Block<out stmt> | ";" (. stmt = null; .) )
	(.
		
		List<ParameterDeclarationExpression> parameters = new List<ParameterDeclarationExpression>();
		parameters.Add(new ParameterDeclarationExpression(type, varName));
		OperatorDeclaration operatorDeclaration = new OperatorDeclaration(m.Modifier, 
		                                                                  attributes, 
		                                                                  parameters, 
		                                                                  operatorType,
		                                                                  isImplicit ? ConversionType.Implicit : ConversionType.Explicit
		                                                                  );
		operatorDeclaration.Body = (BlockStatement)stmt;
		operatorDeclaration.StartLocation = m.GetDeclarationLocation(startPos);
		operatorDeclaration.EndLocation = endPos;
		compilationUnit.AddChild(operatorDeclaration);
	.)
	
	/*--- inner type declaration: */
	| TypeDecl<m, attributes>
	| Type<out type>                       (. Point startPos = t.Location;  .)
	(
		/*--- operator declaration: */     (. OverloadableOperatorType op;
		                                      m.Check(Modifier.Operators);
		                                      if (m.isNone) Error("at least one modifier must be set");
		                                   .)
		"operator" OverloadableOperator<out op> (. TypeReference firstType, secondType = null; string secondName = null; .)
		"(" Type<out firstType> ident (. string firstName = t.val; .)
		( "," Type<out secondType> ident (. secondName = t.val; .)        /* (. if (Tokens.OverloadableUnaryOp[op.kind] && !Tokens.OverloadableBinaryOp[op.kind])
		                                      Error("too many operands for unary operator"); 
		                                   .)*/
		| /* empty */                      /*(. if (Tokens.OverloadableBinaryOp[op.kind]){
		                                      	Error("too few operands for binary operator");
		                                      }
		                                   .)*/
		)
		(. Point endPos = t.Location; .)
		")" ( Block<out stmt> | ";" )
		(.
			List<ParameterDeclarationExpression> parameters = new List<ParameterDeclarationExpression>();
			parameters.Add(new ParameterDeclarationExpression(firstType, firstName));
			if (secondType != null) {
				parameters.Add(new ParameterDeclarationExpression(secondType, secondName));
			}
			OperatorDeclaration operatorDeclaration = new OperatorDeclaration(m.Modifier,
			                                                                  attributes,
			                                                                  parameters,
			                                                                  type,
			                                                                  op);
			operatorDeclaration.Body = (BlockStatement)stmt;
			operatorDeclaration.StartLocation = m.GetDeclarationLocation(startPos);
			operatorDeclaration.EndLocation = endPos;
			compilationUnit.AddChild(operatorDeclaration);
		.)
		
		/*--- field declaration: */
	| IF (IsVarDecl())         (. m.Check(Modifier.Fields); 
		                          FieldDeclaration fd = new FieldDeclaration(attributes, type, m.Modifier);
		                          fd.StartLocation = m.GetDeclarationLocation(startPos); 
		                       .)
		VariableDeclarator<variableDeclarators>
		{ "," VariableDeclarator<variableDeclarators> }
		";"                                (. fd.EndLocation = t.EndLocation; fd.Fields = variableDeclarators; compilationUnit.AddChild(fd); .)
		
		/*--- unqualified indexer declaration (without interface name): */
		|                                  (. m.Check(Modifier.Indexers); .)
		"this" "[" FormalParameterList<p> "]" (. Point endLocation = t.EndLocation; .) "{" (.
			         IndexerDeclaration indexer = new IndexerDeclaration(type, p, m.Modifier, attributes);
			         indexer.StartLocation = startPos;
			         indexer.EndLocation   = endLocation;
			         indexer.BodyStart     = t.Location;
			         PropertyGetRegion getRegion;
			         PropertySetRegion setRegion;
			       .) 
		AccessorDecls<out getRegion, out setRegion> "}" (. 
			          indexer.BodyEnd    = t.EndLocation;
			          indexer.GetRegion = getRegion;
			          indexer.SetRegion = setRegion;
			          compilationUnit.AddChild(indexer);
			       .)
	|  IF (la.kind == Tokens.Identifier)
		( IF (IsExplicitInterfaceImplementation())
			TypeName<out explicitInterface, false>
			(.if (la.kind != Tokens.Dot || Peek(1).kind != Tokens.This) {
				qualident = TypeReference.StripLastIdentifierFromType(ref explicitInterface);
			  } .)
		|	ident (. qualident = t.val; .)
		)
		(. Point qualIdentEndLocation = t.EndLocation; .)
		
		(
			/*--- "not void" method (function) declaration: */
			(                              (. m.Check(Modifier.PropertysEventsMethods); .)
				/* .NET 2.0 */
				[ TypeParameterList<templates> ]
				"(" [ FormalParameterList<p> ] ")" (.
					MethodDeclaration methodDeclaration = new MethodDeclaration(qualident,
					                                                            m.Modifier, 
					                                                            type, 
					                                                            p, 
					                                                            attributes);
					if (explicitInterface != null)
						methodDeclaration.InterfaceImplementations.Add(new InterfaceImplementation(explicitInterface, qualident));
					methodDeclaration.StartLocation = m.GetDeclarationLocation(startPos);
					methodDeclaration.EndLocation   = t.EndLocation;
					methodDeclaration.Templates = templates;
					compilationUnit.AddChild(methodDeclaration);
				                                       .)
				{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
				( Block<out stmt> | ";" ) (. methodDeclaration.Body  = (BlockStatement)stmt; .)
			
			/*--- property declaration: */  
			| "{" (. PropertyDeclaration pDecl = new PropertyDeclaration(qualident, type, m.Modifier, attributes); 
					 if (explicitInterface != null)
						pDecl.InterfaceImplementations.Add(new InterfaceImplementation(explicitInterface, qualident));
			         pDecl.StartLocation = m.GetDeclarationLocation(startPos);
			         pDecl.EndLocation   = qualIdentEndLocation;
			         pDecl.BodyStart   = t.Location;
			         PropertyGetRegion getRegion;
			         PropertySetRegion setRegion;
			      .)
			   AccessorDecls<out getRegion, out setRegion> 
			   "}" (. 
			          pDecl.GetRegion = getRegion;
			          pDecl.SetRegion = setRegion;
			          pDecl.BodyEnd = t.EndLocation;
			          compilationUnit.AddChild(pDecl);
			       .)
			)
			
			/*--- qualified indexer declaration (with interface name): */
			|                              (. m.Check(Modifier.Indexers); .)
			"." "this" "[" FormalParameterList<p> "]" (.
			         IndexerDeclaration indexer = new IndexerDeclaration(type, p, m.Modifier, attributes);
			         indexer.StartLocation = m.GetDeclarationLocation(startPos);
			         indexer.EndLocation   = t.EndLocation;
			         if (explicitInterface != null)
						indexer.InterfaceImplementations.Add(new InterfaceImplementation(explicitInterface, "this"));
			         PropertyGetRegion getRegion;
			         PropertySetRegion setRegion;
			       .) 
			  "{" (. Point bodyStart = t.Location; .)
			  AccessorDecls<out getRegion, out setRegion> 
			  "}"  (. indexer.BodyStart = bodyStart;
			          indexer.BodyEnd   = t.EndLocation;
			          indexer.GetRegion = getRegion;
			          indexer.SetRegion = setRegion;
			          compilationUnit.AddChild(indexer);
			       .)
		)
	)
.

ClassMemberDecl<Modifiers m, List<AttributeSection> attributes>
(. Statement stmt = null; .)
=
	StructMemberDecl<m, attributes>
	| /*--- destructor declaration: */ (. m.Check(Modifier.Destructors); Point startPos = t.Location; .)
	"~" ident                          (. DestructorDeclaration d = new DestructorDeclaration(t.val, m.Modifier, attributes); 
	                                      d.Modifier = m.Modifier;
	                                      d.StartLocation = m.GetDeclarationLocation(startPos);
	                                   .)
	"(" ")" (. d.EndLocation = t.EndLocation; .) ( Block<out stmt> | ";" )  (. 
	                                      d.Body = (BlockStatement)stmt;
	                                      compilationUnit.AddChild(d);
	                                   .)
.

InterfaceMemberDecl
(.
	TypeReference type;
	
	AttributeSection section;
	Modifier mod = Modifier.None;
	List<AttributeSection> attributes = new List<AttributeSection>();
	List<ParameterDeclarationExpression> parameters = new List<ParameterDeclarationExpression>();
	string name;
	PropertyGetRegion getBlock;
	PropertySetRegion setBlock;
	Point startLocation = new Point(-1, -1);
	List<TemplateDefinition> templates = new List<TemplateDefinition>();
.)
=
	{ AttributeSection<out section>     (. attributes.Add(section); .)}
	[ "new" (. mod = Modifier.New; startLocation = t.Location; .) ]
	(
		/*--- interface void method (procedure) declaration: */
		IF (NotVoidPointer()) "void" (. if (startLocation.X == -1) startLocation = t.Location; .) ident (. name = t.val; .)
		[ TypeParameterList<templates> ]
		"(" [ FormalParameterList<parameters> ] ")"
		{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
		";"
		(.  MethodDeclaration md = new MethodDeclaration(name, mod, new TypeReference("void"), parameters, attributes);
			md.StartLocation = startLocation;
			md.EndLocation = t.EndLocation;
			md.Templates = templates;
			compilationUnit.AddChild(md);
		.)
		| (
			Type<out type> (. if (startLocation.X == -1) startLocation = t.Location; .)
			(
				ident                  (. name = t.val; Point qualIdentEndLocation = t.EndLocation; .)
				(
					/*--- interface "not void" method (function) declaration: */
					/* .NET 2.0 */
					[ TypeParameterList<templates> ]
					"(" [ FormalParameterList<parameters> ] ")" 
					/* .NET 2.0 */
					{ IF (IdentIsWhere()) TypeParameterConstraintsClause<templates> }
					";" (.  MethodDeclaration md = new MethodDeclaration(name, mod, type, parameters, attributes);
							md.StartLocation = startLocation;
							md.EndLocation = t.EndLocation;
							md.Templates = templates;
							compilationUnit.AddChild(md);
						.)
					/*--- interface property declaration: */
					|                   (. PropertyDeclaration pd = new PropertyDeclaration(name, type, mod, attributes); compilationUnit.AddChild(pd); .)
					"{" (. Point bodyStart = t.Location;.) InterfaceAccessors<out getBlock, out setBlock> "}" (. pd.GetRegion = getBlock; pd.SetRegion = setBlock; pd.StartLocation = startLocation; pd.EndLocation = qualIdentEndLocation; pd.BodyStart = bodyStart; pd.BodyEnd = t.EndLocation; .)
				)
				/*--- interface indexer declaration: */
				| "this" "[" FormalParameterList<parameters> "]" (.Point bracketEndLocation = t.EndLocation; .)  (. IndexerDeclaration id = new IndexerDeclaration(type, parameters, mod, attributes); compilationUnit.AddChild(id); .)
				"{" (. Point bodyStart = t.Location;.) InterfaceAccessors<out getBlock, out setBlock> "}" (. id.GetRegion = getBlock; id.SetRegion = setBlock; id.StartLocation = startLocation;  id.EndLocation = bracketEndLocation; id.BodyStart = bodyStart; id.BodyEnd = t.EndLocation;.)
			)
			/*--- interface event declaration: */
			| "event" (. if (startLocation.X == -1) startLocation = t.Location; .) Type<out type> ident (. EventDeclaration ed = new EventDeclaration(type, t.val, mod, attributes);
			                                  compilationUnit.AddChild(ed);
			                               .)
			";"                            (. ed.StartLocation = startLocation; ed.EndLocation = t.EndLocation; .)
		)
	)
.

EnumMemberDecl<out FieldDeclaration f>
(.
	Expression expr = null;
	List<AttributeSection> attributes = new List<AttributeSection>();
	AttributeSection section = null;
	VariableDeclaration varDecl = null;
.)
=
	{ AttributeSection<out section> (. attributes.Add(section); .) }
	ident                           (. f = new FieldDeclaration(attributes);
	                                   varDecl         = new VariableDeclaration(t.val);
	                                   f.Fields.Add(varDecl);
	                                   f.StartLocation = t.Location;
	                                .)
	[ "=" Expr<out expr> (. varDecl.Initializer = expr; .) ]
.


AccessorDecls<out PropertyGetRegion getBlock, out PropertySetRegion setBlock>
(.
	List<AttributeSection> attributes = new List<AttributeSection>(); 
	AttributeSection section;
	getBlock = null;
	setBlock = null; 
	Modifiers modifiers = null;
.)
=
	{ AttributeSection<out section> (. attributes.Add(section); .) }
	[ AccessorModifiers<out modifiers> ]
	(
		IF (IdentIsGet())
			GetAccessorDecl<out getBlock, attributes>
			(. if (modifiers != null) {getBlock.Modifier = modifiers.Modifier; } .)
			[  (. attributes = new List<AttributeSection>(); modifiers = null; .)
				{ AttributeSection<out section> (. attributes.Add(section); .) }
				[ AccessorModifiers<out modifiers> ]
				SetAccessorDecl<out setBlock, attributes>
				(. if (modifiers != null) {setBlock.Modifier = modifiers.Modifier; } .)
			]
		| IF (IdentIsSet())
			SetAccessorDecl<out setBlock, attributes>
			(. if (modifiers != null) {setBlock.Modifier = modifiers.Modifier; } .)
			[  (. attributes = new List<AttributeSection>(); modifiers = null; .)
				{ AttributeSection<out section> (. attributes.Add(section); .) }
				[ AccessorModifiers<out modifiers> ]
				GetAccessorDecl<out getBlock, attributes>
				(. if (modifiers != null) {getBlock.Modifier = modifiers.Modifier; } .)
			]
		| ident (. Error("get or set accessor declaration expected"); .)
	)
.

GetAccessorDecl<out PropertyGetRegion getBlock, List<AttributeSection> attributes>
(. Statement stmt = null; .)
=
	ident /* "get" is not a keyword! */
	(. if (t.val != "get") Error("get expected"); .)
	(. Point startLocation = t.Location; .)
	( Block<out stmt> | ";" )
	(. getBlock = new PropertyGetRegion((BlockStatement)stmt, attributes); .)
	(. getBlock.StartLocation = startLocation; getBlock.EndLocation = t.EndLocation; .)
.

SetAccessorDecl<out PropertySetRegion setBlock, List<AttributeSection> attributes>
(. Statement stmt = null; .)
=
	ident /* "set" is not a keyword! */
	(. if (t.val != "set") Error("set expected"); .)
	(. Point startLocation = t.Location; .)
	( Block<out stmt> | ";" )
	(. setBlock = new PropertySetRegion((BlockStatement)stmt, attributes); .)
	(. setBlock.StartLocation = startLocation; setBlock.EndLocation = t.EndLocation; .)
.

EventAccessorDecls<out EventAddRegion addBlock, out EventRemoveRegion removeBlock>
(. AttributeSection section;
   List<AttributeSection> attributes = new List<AttributeSection>();
   Statement stmt;
   addBlock = null;
   removeBlock = null;
.)
=
	{ AttributeSection<out section> (. attributes.Add(section); .) }
	(
		IF (IdentIsAdd())            (. addBlock = new EventAddRegion(attributes); .)
			AddAccessorDecl<out stmt>       (. attributes = new List<AttributeSection>(); addBlock.Block = (BlockStatement)stmt; .)
			{ AttributeSection<out section> (. attributes.Add(section); .)}
			RemoveAccessorDecl<out stmt>    (. removeBlock = new EventRemoveRegion(attributes); removeBlock.Block = (BlockStatement)stmt; .)
		| IF (IdentIsRemove())
			RemoveAccessorDecl <out stmt>    (. removeBlock = new EventRemoveRegion(attributes); removeBlock.Block = (BlockStatement)stmt; attributes = new List<AttributeSection>(); .)
			{ AttributeSection<out section>  (. attributes.Add(section); .) }
			AddAccessorDecl<out stmt>        (. addBlock = new EventAddRegion(attributes); addBlock.Block = (BlockStatement)stmt; .)
		| ident (. Error("add or remove accessor declaration expected"); .)
	)
.

InterfaceAccessors<out PropertyGetRegion getBlock, out PropertySetRegion setBlock>
(.
	AttributeSection section;
	List<AttributeSection> attributes = new List<AttributeSection>();
	getBlock = null; setBlock = null;
	PropertyGetSetRegion lastBlock = null;
.)
=
	{ AttributeSection<out section> (. attributes.Add(section); .) }
	(. Point startLocation = la.Location; .)
	(
		IF (IdentIsGet()) ident   (. getBlock = new PropertyGetRegion(null, attributes); .)
		| IF (IdentIsSet()) ident (. setBlock = new PropertySetRegion(null, attributes); .)
		| ident                   (. Error("set or get expected"); .)
	)
	";"
	(. if (getBlock != null) { getBlock.StartLocation = startLocation; getBlock.EndLocation = t.EndLocation; }
	   if (setBlock != null) { setBlock.StartLocation = startLocation; setBlock.EndLocation = t.EndLocation; }
	   attributes = new List<AttributeSection>(); .)
	[
		{ AttributeSection<out section> (. attributes.Add(section); .) }
		(. startLocation = la.Location; .)
		(
			IF (IdentIsGet()) ident   (. if (getBlock != null) Error("get already declared");
			                             else { getBlock = new PropertyGetRegion(null, attributes); lastBlock = getBlock; }
			                          .)
			| IF (IdentIsSet()) ident (. if (setBlock != null) Error("set already declared");
			                             else { setBlock = new PropertySetRegion(null, attributes); lastBlock = setBlock; }
			                          .)
			| ident                   (. Error("set or get expected"); .)
		)
		";"
		(. if (lastBlock != null) { lastBlock.StartLocation = startLocation; lastBlock.EndLocation = t.EndLocation; } .)
	]
.

VariableDeclarator<List<VariableDeclaration> fieldDeclaration>
(. Expression expr = null; .)
=
	ident                                 (. VariableDeclaration f = new VariableDeclaration(t.val); .)
	[ "=" VariableInitializer<out expr>   (. f.Initializer = expr; .) ] (. fieldDeclaration.Add(f); .)
.

Block<out Statement stmt> /* not BlockStatement because of EmbeddedStatement */
=
	"{" (. BlockStatement blockStmt = new BlockStatement();
	       blockStmt.StartLocation = t.EndLocation;
	       compilationUnit.BlockStart(blockStmt);
	       if (!parseMethodContents) lexer.SkipCurrentBlock();
	    .)
	{ Statement }
	"}" (. 
	       stmt = blockStmt;
	       blockStmt.EndLocation = t.EndLocation;
	       compilationUnit.BlockEnd();
	    .)
.

AddAccessorDecl<out Statement stmt>
(.stmt = null;.) 
=
	/* "add" is not a keyword!? */
	ident (. if (t.val != "add") Error("add expected"); .)
	Block<out stmt>
.

RemoveAccessorDecl<out Statement stmt>
(.stmt = null;.) 
=
	/* "remove" is not a keyword!? */
	ident (. if (t.val != "remove") Error("remove expected"); .)
	Block<out stmt>
.

ConstructorInitializer<out ConstructorInitializer ci>
(. Expression expr; ci = new ConstructorInitializer(); .)
=
	":"
	(
		"base" (. ci.ConstructorInitializerType = ConstructorInitializerType.Base; .)
		| "this"  (. ci.ConstructorInitializerType = ConstructorInitializerType.This; .)
	) 
	"("
	[ Argument<out expr> (. if (expr != null) { ci.Arguments.Add(expr); } .) { "," Argument<out expr> (. if (expr != null) { ci.Arguments.Add(expr); } .) } ]
	")"
.

VariableInitializer<out Expression initializerExpression>
(. TypeReference type = null; Expression expr = null; initializerExpression = null; .)
=
	Expr<out initializerExpression>
	| ArrayInitializer<out initializerExpression>
	| "stackalloc" Type<out type> "[" Expr<out expr> "]" (. initializerExpression = new StackAllocExpression(type, expr); .)
	| /* workaround for coco bug? doesn't work in Expr production in this case. */
	  "default" "(" Type<out type> ")" (. initializerExpression = new DefaultValueExpression(type); .)
.

OverloadableOperator<out OverloadableOperatorType op>
(. op = OverloadableOperatorType.None; .)
=
	"+"      (. op = OverloadableOperatorType.Add; .)
	| "-"    (. op = OverloadableOperatorType.Subtract; .)
	
	| "!"    (. op = OverloadableOperatorType.Not; .)
	| "~"    (. op = OverloadableOperatorType.BitNot; .)
	
	| "++"   (. op = OverloadableOperatorType.Increment; .)
	| "--"   (. op = OverloadableOperatorType.Decrement; .)
	
	| "true"   (. op = OverloadableOperatorType.True; .)
	| "false"   (. op = OverloadableOperatorType.False; .)
	
	| "*"    (. op = OverloadableOperatorType.Multiply; .)
	| "/"    (. op = OverloadableOperatorType.Divide; .)
	| "%"    (. op = OverloadableOperatorType.Modulus; .)
	
	| "&"    (. op = OverloadableOperatorType.BitwiseAnd; .)
	| "|"    (. op = OverloadableOperatorType.BitwiseOr; .)
	| "^"    (. op = OverloadableOperatorType.ExclusiveOr; .)
	
	| "<<"   (. op = OverloadableOperatorType.ShiftLeft; .)
	| "=="   (. op = OverloadableOperatorType.Equality; .)
	| "!="    (. op = OverloadableOperatorType.InEquality; .)
	| "<"     (. op = OverloadableOperatorType.LessThan; .)
	| ">="    (. op = OverloadableOperatorType.GreaterThanOrEqual; .)
	| "<="    (. op = OverloadableOperatorType.LessThanOrEqual; .)
	| ">"     (. op = OverloadableOperatorType.GreaterThan; .) [ ">" (. op = OverloadableOperatorType.ShiftRight; .) ]
.

Argument<out Expression argumentexpr>
(.
	Expression expr;
	FieldDirection fd = FieldDirection.None;
.)
=
	[
		"ref" (. fd = FieldDirection.Ref; .)
		| "out" (. fd = FieldDirection.Out; .)
	]
	Expr<out expr> (. argumentexpr = fd != FieldDirection.None ? argumentexpr = new DirectionExpression(fd, expr) : expr; .)
.

AssignmentOperator<out AssignmentOperatorType op>
(. op = AssignmentOperatorType.None; .)
=
	"="     (. op = AssignmentOperatorType.Assign; .)
	| "+="  (. op = AssignmentOperatorType.Add; .)
	| "-="  (. op = AssignmentOperatorType.Subtract; .)
	| "*="  (. op = AssignmentOperatorType.Multiply; .)
	| "/="  (. op = AssignmentOperatorType.Divide; .)
	| "%="  (. op = AssignmentOperatorType.Modulus; .)
	| "&="  (. op = AssignmentOperatorType.BitwiseAnd; .)
	| "|="  (. op = AssignmentOperatorType.BitwiseOr; .)
	| "^="  (. op = AssignmentOperatorType.ExclusiveOr; .)
	| "<<=" (. op = AssignmentOperatorType.ShiftLeft; .)
	| IF (la.kind == Tokens.GreaterThan && Peek(1).kind == Tokens.GreaterEqual)
		">" ">=" (. op = AssignmentOperatorType.ShiftRight; .)
.

ArrayInitializer<out Expression outExpr>
(.
	Expression expr = null;
	ArrayInitializerExpression initializer = new ArrayInitializerExpression();
.)
=
	"{"
	[	VariableInitializer<out expr>
		(. if (expr != null) { initializer.CreateExpressions.Add(expr); } .)
		{ IF (NotFinalComma())
			"," VariableInitializer<out expr>
			(. if (expr != null) { initializer.CreateExpressions.Add(expr); } .)
		}
		[ "," ]
	]
	"}" (. outExpr = initializer; .)
.

LocalVariableDecl<out Statement stmt>
(.
	TypeReference type;
	VariableDeclaration      var = null;
	LocalVariableDeclaration localVariableDeclaration; 
.)
=
	Type<out type> (. localVariableDeclaration = new LocalVariableDeclaration(type); localVariableDeclaration.StartLocation = t.Location; .)
	LocalVariableDeclarator<out var> (. localVariableDeclaration.Variables.Add(var); .)
	{ "," LocalVariableDeclarator<out var> (. localVariableDeclaration.Variables.Add(var); .) }
	(. stmt = localVariableDeclaration; .)
.

LocalVariableDeclarator<out VariableDeclaration var>
(. Expression expr = null; .)
=
/*	ident (. var = new VariableDeclaration(t.val); .) [ "=" LocalVariableInitializer<out expr> (. var.Initializer = expr; .) ]*/
	ident (. var = new VariableDeclaration(t.val); .) [ "=" VariableInitializer<out expr> (. var.Initializer = expr; .) ]
.
/*
LocalVariableInitializer<out Expression expr>
(. expr = null; .)
=
	Expr<out expr>
	| ArrayInitializer<out expr>
.
*/
Statement
(.
	TypeReference type;
	Expression expr;
	Statement stmt = null;
	Point startPos = la.Location;
.)
=
	(
		/*--- labeled statement: */
		IF (IsLabel()) ident (. compilationUnit.AddChild(new LabelStatement(t.val)); .)
		":" Statement
		/*--- local constant declaration: */
		| "const" Type<out type> (. LocalVariableDeclaration var = new LocalVariableDeclaration(type, Modifier.Const); string ident = null; var.StartLocation = t.Location; .) 
		  ident (. ident = t.val; .)
		  "=" Expr<out expr> (. var.Variables.Add(new VariableDeclaration(ident, expr)); .)
		  { "," ident (. ident = t.val; .) "=" Expr<out expr> (. var.Variables.Add(new VariableDeclaration(ident, expr)); .) }
		  ";" (. compilationUnit.AddChild(var); .)
		/*--- local variable declaration: */
		| IF (IsLocalVarDecl()) LocalVariableDecl<out stmt> ";" (. compilationUnit.AddChild(stmt); .)
		| EmbeddedStatement<out stmt> (. compilationUnit.AddChild(stmt); .)
		/* LL(1) confict: LocalVariableDecl *
		 *            <-> StatementExpr     *
		 * ident {"." ident} { "[" Expr ... */
	)
	(.
		if (stmt != null) {
			stmt.StartLocation = startPos;
			stmt.EndLocation = t.EndLocation;
		}
	.)
.

EmbeddedStatement<out Statement statement>
(.
	TypeReference type = null;
	Expression expr = null;
	Statement embeddedStatement = null;
	statement = null;
.)
=
	Block<out statement>
	/*--- empty statement: */
	| ";"                       (. statement = new EmptyStatement(); .)
	/*--- checked / unchecked statement: */
	| IF (UnCheckedAndLBrace()) (. Statement block; bool isChecked = true; .)
	("checked" | "unchecked"    (. isChecked = false;.) )
	Block<out block>            (. statement = isChecked ? (Statement)new CheckedStatement(block) : (Statement)new UncheckedStatement(block); .)
	/*--- selection statements (if, switch): */
	| "if"                      (. Statement elseStatement = null; .)
	"(" Expr<out expr> ")"
	EmbeddedStatement<out embeddedStatement>
	[ "else" EmbeddedStatement<out elseStatement> ]
	                            (. statement = elseStatement != null ? (Statement)new IfElseStatement(expr, embeddedStatement, elseStatement) :  (Statement)new IfElseStatement(expr, embeddedStatement); .)
	| "switch" (. List<SwitchSection> switchSections = new List<SwitchSection>(); SwitchSection switchSection; .)
	  "(" Expr<out expr> ")"
	  "{" { SwitchSection<out switchSection> (. switchSections.Add(switchSection); .) } 
	  "}"  (. statement = new SwitchStatement(expr, switchSections); .)
	/*--- iteration statements (while, do, for, foreach): */
	| "while" "(" Expr<out expr> ")"
	
	EmbeddedStatement<out embeddedStatement> (. statement = new DoLoopStatement(expr, embeddedStatement, ConditionType.While, ConditionPosition.Start);.)
	| "do" EmbeddedStatement<out embeddedStatement> "while"
	"(" Expr<out expr> ")" ";"  (. statement = new DoLoopStatement(expr, embeddedStatement, ConditionType.While, ConditionPosition.End); .)
	| "for" (. ArrayList initializer = null; ArrayList iterator = null; .)
	  "(" [ ForInitializer<out initializer> ] ";"
	  [ Expr<out expr> ] ";"
	  [ ForIterator<out iterator> ] ")"
	  EmbeddedStatement<out embeddedStatement> (. statement = new ForStatement(initializer, expr, iterator, embeddedStatement); .)
	| "foreach" "(" Type<out type> ident     (. string varName = t.val; Point start = t.Location;.)
	"in" Expr<out expr> ")"
	EmbeddedStatement<out embeddedStatement> (.  statement = new ForeachStatement(type, varName , expr, embeddedStatement); 
	                                             statement.EndLocation = t.EndLocation;
	                                         .)
	/*--- jump statements (break, contine, goto, return, throw): */
	| "break" ";"               (. statement = new BreakStatement(); .)
	| "continue" ";"            (. statement = new ContinueStatement(); .)
	| GotoStatement<out statement>
	| IF (IsYieldStatement()) ident ( "return" Expr<out expr> (. statement = new YieldStatement(new ReturnStatement(expr)); .)
	                                | "break" (. statement = new YieldStatement(new BreakStatement()); .) ) ";"
	| "return" [ Expr<out expr> ] ";"    (. statement = new ReturnStatement(expr); .)
	| "throw" [ Expr<out expr> ] ";"     (. statement = new ThrowStatement(expr); .)
	/*--- expression statement: */
	| StatementExpr<out statement> ";"
	/*--- try statement: */
	| TryStatement<out statement>
	/*--- lock satement: */
	| "lock" "(" Expr<out expr> ")"
	EmbeddedStatement<out embeddedStatement> (. statement = new LockStatement(expr, embeddedStatement); .)
	/*--- using statement: */
	| (.Statement resourceAcquisitionStmt = null; .)
	"using" "("
	ResourceAcquisition<out resourceAcquisitionStmt> ")"
	EmbeddedStatement<out embeddedStatement> (. statement = new UsingStatement(resourceAcquisitionStmt, embeddedStatement); .)
	/*--- unsafe statement: */
	| "unsafe" Block<out embeddedStatement>  (. statement = new UnsafeStatement(embeddedStatement); .)
	/*--- fixed statement: */
	| "fixed"
	"(" Type<out type>     (. if (type.PointerNestingLevel == 0) Error("can only fix pointer types");
	                          List<VariableDeclaration> pointerDeclarators = new List<VariableDeclaration>(1);
	                       .)
	ident                  (. string identifier = t.val; .)
	"=" Expr<out expr>     (. pointerDeclarators.Add(new VariableDeclaration(identifier, expr)); .)
	{
		"," ident          (. identifier = t.val; .)
		"=" Expr<out expr> (. pointerDeclarators.Add(new VariableDeclaration(identifier, expr)); .)
	}
	")" EmbeddedStatement<out embeddedStatement>  (. statement = new FixedStatement(type, pointerDeclarators, embeddedStatement); .)
.

ForInitializer<out ArrayList initializer>
(.
	Statement stmt; 
	initializer = new ArrayList();
.)
=
	IF (IsLocalVarDecl()) LocalVariableDecl<out stmt> (. initializer.Add(stmt);.)
	| StatementExpr<out stmt> (.initializer.Add(stmt);.) { "," StatementExpr<out stmt> (. initializer.Add(stmt);.) }
.

ForIterator<out ArrayList iterator>
(.
	Statement stmt; 
	iterator = new ArrayList();
.)
=
	StatementExpr<out stmt> (. iterator.Add(stmt);.) { "," StatementExpr<out stmt> (. iterator.Add(stmt); .) }
.

SwitchSection<out SwitchSection stmt>
(.
	SwitchSection switchSection = new SwitchSection();
	CaseLabel label;
.)
=
	SwitchLabel<out label> (. switchSection.SwitchLabels.Add(label); .) 
	{
		SwitchLabel<out label> (. switchSection.SwitchLabels.Add(label); .) 
	}
	(. compilationUnit.BlockStart(switchSection); .)
	Statement { Statement }
	(.
		compilationUnit.BlockEnd();
		stmt = switchSection;
	.)
.

SwitchLabel<out CaseLabel label>
 (. Expression expr = null; label = null; .)
=
	"case" Expr<out expr> ":" (. label =  new CaseLabel(expr); .)
	| "default" ":" (. label =  new CaseLabel(); .)
.

TryStatement<out Statement tryStatement>
(.
	Statement blockStmt = null, finallyStmt = null;
	List<CatchClause> catchClauses = null;
.)
=
	"try"  Block<out blockStmt>
	(
		CatchClauses<out catchClauses> [ "finally" Block<out finallyStmt> ]
		| "finally" Block<out finallyStmt>
	)
	(.
		tryStatement = new TryCatchStatement(blockStmt, catchClauses, finallyStmt);
	
	.)
.

CatchClauses<out List<CatchClause> catchClauses>
(.
	catchClauses = new List<CatchClause>();
.)
=
	"catch" (. string identifier;
	           Statement stmt;
	           TypeReference typeRef;
	        .)
	/*--- general catch clause (as only catch clause) */
	(
		Block<out stmt> (. catchClauses.Add(new CatchClause(stmt)); .)
		/*--- specific catch clause */
		| "(" ClassType<out typeRef, false> (. identifier = null; .)
			[ ident (. identifier = t.val; .) ]
		   ")" Block<out stmt> 
		   (. catchClauses.Add(new CatchClause(typeRef, identifier, stmt)); .)
		{ IF (IsTypedCatch()) "catch" "(" ClassType<out typeRef, false> (. identifier = null; .)
			[ ident (. identifier = t.val; .) ]
		   ")" Block<out stmt>
		   (. catchClauses.Add(new CatchClause(typeRef, identifier, stmt)); .) }
		/*--- general catch clause (after specific catch clauses, optional) */
		[ "catch" Block<out stmt> (. catchClauses.Add(new CatchClause(stmt)); .) ]
	)
.

GotoStatement<out Statement stmt>
(. Expression expr; stmt = null; .)
=
	"goto"
	(
		ident (. stmt = new GotoStatement(t.val); .) ";"
		| "case" Expr<out expr>  ";" (. stmt = new GotoCaseStatement(expr); .)
		| "default" ";" (. stmt = new GotoCaseStatement(null); .)
	)
.

ResourceAcquisition<out Statement stmt>
(.
	stmt = null;
	Expression expr;
.)
=
	(
		IF (IsLocalVarDecl()) LocalVariableDecl<out stmt>
		| Expr<out expr> /* LL(1) conflict resoltion:                             *
		                  * check if next is Qualident followed by ident          *
		                  * ==> LocalVariableDecl                                 *
		                  * new problem: first set of ResourceAcquisition changes */
		(. stmt = new StatementExpression(expr); .)
	)
.

StatementExpr<out Statement stmt>
(. Expression expr; .)
=
	Expr<out expr>
	/* The grammar allows only assignments or method invocations here, */
	/* but we don't enforce that here */
	(. stmt = new StatementExpression(expr); .)
.

Expr<out Expression expr>
(. expr = null; Expression expr1 = null, expr2 = null; AssignmentOperatorType op; .)
=
	UnaryExpr<out expr>
	/*--- conditional expression: */
	(	
		( AssignmentOperator<out op> Expr<out expr1> (. expr = new AssignmentExpression(expr, op, expr1); .) )
		| IF (la.kind == Tokens.GreaterThan && Peek(1).kind == Tokens.GreaterEqual)
		  ( AssignmentOperator<out op> Expr<out expr1> (. expr = new AssignmentExpression(expr, op, expr1); .) )
		| (
			ConditionalOrExpr<ref expr>
			[ "??" Expr<out expr1> (. expr = new BinaryOperatorExpression(expr, BinaryOperatorType.NullCoalescing, expr1); .) ]
			[ "?" Expr<out expr1> ":" Expr<out expr2> (. expr = new ConditionalExpression(expr, expr1, expr2);  .) ]
		)
	)
.


UnaryExpr<out Expression uExpr>
(.
	TypeReference type = null;
	Expression expr;
	ArrayList  expressions = new ArrayList();
	uExpr = null;
.)
=
	{
		/* IF (Tokens.UnaryOp[la.kind] || IsTypeCast()) */
		(
			  "+"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Plus)); .)
			| "-"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Minus)); .)
			| "!"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Not)); .)
			| "~"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.BitNot)); .)
			| "*"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Star)); .)
			| "++" (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Increment)); .)
			| "--" (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.Decrement)); .)
			| "&"  (. expressions.Add(new UnaryOperatorExpression(UnaryOperatorType.BitWiseAnd)); .)
			
			/*--- cast expression: */
			/* Problem:  "(" Type ")" from here and                     *
			 *           "(" Expr ")" from PrimaryExpr                  *
			 *           are not distinguishable                        *
			 * Solution: (in IsTypeCast())                              *
			 * use external information from compiled assembly or guess */
			| IF (IsTypeCast()) "(" Type<out type> ")"  (.  expressions.Add(new CastExpression(type)); .)
		)
	}
	
	PrimaryExpr<out expr> (. for (int i = 0; i < expressions.Count; ++i) {
	                         	Expression nextExpression = i + 1 < expressions.Count ? (Expression)expressions[i + 1] : expr;
	                         	if (expressions[i] is CastExpression) {
	                         		((CastExpression)expressions[i]).Expression = nextExpression;
	                         	} else {
	                         		((UnaryOperatorExpression)expressions[i]).Expression = nextExpression;
	                         	}
	                         }
	                         if (expressions.Count > 0) {
	                         	uExpr = (Expression)expressions[0];
	                         } else {
	                         	uExpr = expr;
	                         }
	                      .)
.


PrimaryExpr<out Expression pexpr>
(.
	TypeReference type = null;
	List<TypeReference> typeList = null;
	bool isArrayCreation = false;
	Expression expr;
	pexpr = null;
.)
=
	(
		"true"                              (.pexpr = new PrimitiveExpression(true, "true");  .)
		| "false"                           (.pexpr = new PrimitiveExpression(false, "false"); .)
		| "null"                            (.pexpr = new PrimitiveExpression(null, "null");  .)          /* from literal token */
		| Literal                           (.pexpr = new PrimitiveExpression(t.literalValue, t.val);  .)
		| IF (la.kind == Tokens.Identifier && Peek(1).kind == Tokens.DoubleColon)
			ident (. type = new TypeReference(t.val); .)
			"::"  (. pexpr = new TypeReferenceExpression(type); .)
			ident (. if (type.Type == "global") { type.IsGlobal = true; type.Type = t.val; } else type.Type += "." + t.val; .)
		/*--- simple name: */
		| ident (. pexpr = new IdentifierExpression(t.val); .)
		/*--- parenthesized expression: */
		| "(" Expr<out expr> ")" (. pexpr = new ParenthesizedExpression(expr); .)
		| /*--- predefined type member access: */
		(. string val = null; .)
		(
			  "bool" (. val = "bool"; .) 
			| "byte" (. val = "byte"; .)   
			| "char" (. val = "char"; .)
			| "decimal" (. val = "decimal"; .)
			| "double"  (. val = "double"; .)
			| "float"   (. val = "float"; .)
			| "int"     (. val = "int"; .)
			| "long"  (. val = "long"; .)
			| "object"   (. val = "object"; .)
			| "sbyte" (. val = "sbyte"; .)
			| "short"   (. val = "short"; .)
			| "string"  (. val = "string"; .)
			| "uint"  (. val = "uint"; .)
			| "ulong"    (. val = "ulong"; .)
			| "ushort" (. val = "ushort"; .)
		) (. t.val = ""; .) "." ident (. pexpr = new FieldReferenceExpression(new TypeReferenceExpression(val), t.val); .)
		/*--- this access: */
		| "this"                              (. pexpr = new ThisReferenceExpression(); .)
		/*--- base access: */
		| "base"                              (. Expression retExpr = new BaseReferenceExpression(); .)
		(
			"." ident                         (. retExpr = new FieldReferenceExpression(retExpr, t.val); .)
			| "[" Expr<out expr>              (. ArrayList indices = new ArrayList(); if (expr != null) { indices.Add(expr); } .)
			{ "," Expr<out expr>              (. if (expr != null) { indices.Add(expr); } .) }
			"]"                               (. retExpr = new IndexerExpression(retExpr, indices); .)
		)                                     (. pexpr = retExpr; .)
		|	"new" NonArrayType<out type>
			(. List<Expression> parameters = new List<Expression>(); .)
			/*--- delegate / object creation expression: */
			/* Note: a delegate creation expression allow only a single Expr  */
			/*       not an argument list, but this is not distinguished here */
			(
				"(" (. ObjectCreateExpression oce = new ObjectCreateExpression(type, parameters); .)
				    [ Argument<out expr>          (. if (expr != null) { parameters.Add(expr); } .)
				      { "," Argument<out expr>    (. if (expr != null) { parameters.Add(expr); } .) }
				    ]
				")" (. pexpr = oce; .)
			|	"["  /*--- array creation expression: */
				(. isArrayCreation = true; ArrayCreateExpression ace = new ArrayCreateExpression(type); pexpr = ace; .)
				(. int dims = 0; List<int> ranks = new List<int>(); .)
				(
					{ "," (. dims += 1; .) }
					"]" (. ranks.Add(dims); dims = 0; .)
					{ "[" { "," (. ++dims; .) } "]" (. ranks.Add(dims); dims = 0; .) }
					(. ace.CreateType.RankSpecifier = ranks.ToArray(); .)
					ArrayInitializer<out expr> (. ace.ArrayInitializer = (ArrayInitializerExpression)expr; .)
				|	Expr<out expr> (. if (expr != null) parameters.Add(expr); .)
					{	"," (. dims += 1; .)
						Expr<out expr> (. if (expr != null) parameters.Add(expr); .)
					}
					"]" (. ranks.Add(dims); ace.Arguments = parameters; dims = 0; .)
					{ "[" { "," (. ++dims; .) } "]" (. ranks.Add(dims); dims = 0; .) }
					(. ace.CreateType.RankSpecifier = ranks.ToArray(); .)
					[ ArrayInitializer<out expr> (. ace.ArrayInitializer = (ArrayInitializerExpression)expr; .) ]
				)
			)
		| "typeof" "("
		(
			IF (NotVoidPointer()) "void" (. type = new TypeReference("void"); .)
			| TypeWithRestriction<out type, true, true>
		) ")"                            (. pexpr = new TypeOfExpression(type); .)
		
		| IF (la.kind == Tokens.Default && Peek(1).kind == Tokens.OpenParenthesis)
			/* possible conflict with switch's default */
			"default" "(" Type<out type> ")" (. pexpr = new DefaultValueExpression(type); .)
		| "sizeof" "(" Type<out type> ")" (. pexpr = new SizeOfExpression(type); .)
		| "checked" "(" Expr<out expr> ")" (. pexpr = new CheckedExpression(expr); .)
		| "unchecked" "(" Expr<out expr> ")" (. pexpr = new UncheckedExpression(expr); .)
		| "delegate" AnonymousMethodExpr<out expr> (. pexpr = expr; .)
	)
	{
		(
			"++"   (. pexpr = new UnaryOperatorExpression(pexpr, UnaryOperatorType.PostIncrement); .)
			| "--" (. pexpr = new UnaryOperatorExpression(pexpr, UnaryOperatorType.PostDecrement); .)
		)
		/*--- member access */
		| "->" ident (. pexpr = new PointerReferenceExpression(pexpr, t.val); .)
		| "." ident  (. pexpr = new FieldReferenceExpression(pexpr, t.val);.)
		/* member access on generic type */
		|   ( IF (IsGenericFollowedBy(Tokens.Dot) && IsTypeReferenceExpression(pexpr))
				TypeArgumentList<out typeList, false> )
				"." ident
				(. pexpr = new FieldReferenceExpression(GetTypeReferenceExpression(pexpr, typeList), t.val);.)
		/*--- invocation expression: */
		| "("                        (. List<Expression> parameters = new List<Expression>(); .)
			[ Argument<out expr>     (. if (expr != null) {parameters.Add(expr);} .)
			{ "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
			} ] ")"                  (. pexpr = new InvocationExpression(pexpr, parameters); .)
		|   ( IF (IsGenericFollowedBy(Tokens.OpenParenthesis)) TypeArgumentList<out typeList, false> )
			"("                      (. List<Expression> parameters = new List<Expression>(); .)
			[ Argument<out expr>     (. if (expr != null) {parameters.Add(expr);} .)
			{ "," Argument<out expr> (. if (expr != null) {parameters.Add(expr);} .)
			} ] ")"                  (. pexpr = new InvocationExpression(pexpr, parameters, typeList); .)
		/*--- element access */
		|  (. if (isArrayCreation) Error("element access not allow on array creation");
		      ArrayList indices = new ArrayList();
		   .)
		"[" Expr<out expr> (. if (expr != null) { indices.Add(expr); } .)
		{ "," Expr<out expr> (. if (expr != null) { indices.Add(expr); } .)
		} "]" (. pexpr = new IndexerExpression(pexpr, indices); .)
	}
.

AnonymousMethodExpr<out Expression outExpr>
(.
	AnonymousMethodExpression expr = new AnonymousMethodExpression();
	expr.StartLocation = t.Location;
	Statement stmt;
	List<ParameterDeclarationExpression> p = new List<ParameterDeclarationExpression>();
	outExpr = expr;
.)
=
	[
		"("
		[ FormalParameterList<p> (. expr.Parameters = p; .) ]
		")"
	]
	/*--- ParseExpression doesn't set a compilation unit, */
	/*--- so we can't use block then -> skip body of anonymous method */
	(. if (compilationUnit != null) { .)
		Block<out stmt>              (. expr.Body  = (BlockStatement)stmt; .)
	(. } else { .)
		"{"
		(. lexer.SkipCurrentBlock(); .)
		"}"
	(. } .)
	(. expr.EndLocation = t.Location; .)
.

ConditionalOrExpr<ref Expression outExpr>
(. Expression expr;   .)
=
	ConditionalAndExpr<ref outExpr>  { "||" UnaryExpr<out expr> ConditionalAndExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, BinaryOperatorType.LogicalOr, expr);  .) }
.

ConditionalAndExpr<ref Expression outExpr>
(. Expression expr; .)
=
	InclusiveOrExpr<ref outExpr>  { "&&" UnaryExpr<out expr> InclusiveOrExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, BinaryOperatorType.LogicalAnd, expr);  .) }
.

InclusiveOrExpr<ref Expression outExpr>
(. Expression expr; .)
=
	ExclusiveOrExpr<ref outExpr>  { "|" UnaryExpr<out expr> ExclusiveOrExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, BinaryOperatorType.BitwiseOr, expr);  .) }
.

ExclusiveOrExpr<ref Expression outExpr>
(. Expression expr; .)
=
	AndExpr<ref outExpr>  { "^" UnaryExpr<out expr> AndExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, BinaryOperatorType.ExclusiveOr, expr);  .) }
.

AndExpr<ref Expression outExpr>
(. Expression expr; .)
=
	EqualityExpr<ref outExpr> { "&" UnaryExpr<out expr> EqualityExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, BinaryOperatorType.BitwiseAnd, expr);  .) }
.

EqualityExpr<ref Expression outExpr>
(.
	Expression expr;
	BinaryOperatorType op = BinaryOperatorType.None;
.)
=
	RelationalExpr<ref outExpr>
	{
		(
			"!="   (. op = BinaryOperatorType.InEquality; .)
			| "==" (. op = BinaryOperatorType.Equality; .)
		)
		UnaryExpr<out expr> RelationalExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, op, expr);  .) 
	}
.

RelationalExpr<ref Expression outExpr>
(.
	TypeReference type;
	Expression expr;
	BinaryOperatorType op = BinaryOperatorType.None;
.)
=
	ShiftExpr<ref outExpr>
	{
		(	"<"    (. op = BinaryOperatorType.LessThan; .)
		|	">"  (. op = BinaryOperatorType.GreaterThan; .)
		|	"<=" (. op = BinaryOperatorType.LessThanOrEqual; .)
		|	">=" (. op = BinaryOperatorType.GreaterThanOrEqual; .)
		)
		UnaryExpr<out expr>
		ShiftExpr<ref expr>
		(. outExpr = new BinaryOperatorExpression(outExpr, op, expr); .)
	|
		(	"is"
			TypeWithRestriction<out type, false, false>
			(. outExpr = new TypeOfIsExpression(outExpr, type); .)
		|	"as"
			TypeWithRestriction<out type, false, false>
			(. outExpr = new CastExpression(type, outExpr, CastType.TryCast); .)
		)
	}
.

ShiftExpr<ref Expression outExpr>
(.
	Expression expr;
	BinaryOperatorType op = BinaryOperatorType.None;
.)
=
	AdditiveExpr<ref outExpr> 
	{
		(	"<<"   (. op = BinaryOperatorType.ShiftLeft; .)
			| IF (IsShiftRight()) (
				">" ">" (. op = BinaryOperatorType.ShiftRight; .)
			)
		)
		UnaryExpr<out expr> AdditiveExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, op, expr);  .) 
	}
.

AdditiveExpr<ref Expression outExpr>
(.
	Expression expr;
	BinaryOperatorType op = BinaryOperatorType.None;
.)
=
	MultiplicativeExpr<ref outExpr>
	{
		(
			"+"   (. op = BinaryOperatorType.Add; .)
			| "-" (. op = BinaryOperatorType.Subtract; .)
		)
		UnaryExpr<out expr> MultiplicativeExpr<ref expr> (.  outExpr = new BinaryOperatorExpression(outExpr, op, expr);  .)
	}
.

MultiplicativeExpr<ref Expression outExpr>
(.
	Expression expr;
	BinaryOperatorType op = BinaryOperatorType.None;
.)
=
	{
		(
			"*"   (. op = BinaryOperatorType.Multiply; .)
			| "/" (. op = BinaryOperatorType.Divide; .)
			| "%" (. op = BinaryOperatorType.Modulus; .)
		) 
		UnaryExpr<out expr> (. outExpr = new BinaryOperatorExpression(outExpr, op, expr); .) 
	}
.

/* .NET 2.0 rules */	

TypeName<out TypeReference typeRef, bool canBeUnbound>
(.	List<TypeReference> typeArguments = null;
	string alias = null;
	string qualident;
.)
=
	[ IF (la.kind == Tokens.Identifier && Peek(1).kind == Tokens.DoubleColon)
		ident (. alias = t.val; .)
		"::"
	]
	Qualident<out qualident>
	[TypeArgumentList<out typeArguments, canBeUnbound>]
	(.
		if (alias == null) {
			typeRef = new TypeReference(qualident, typeArguments);
		} else if (alias == "global") {
			typeRef = new TypeReference(qualident, typeArguments);
			typeRef.IsGlobal = true;
		} else {
			typeRef = new TypeReference(alias + "." + qualident, typeArguments);
		}
	.)
	{ IF (DotAndIdent())
		"." (. typeArguments = null; .)
		Qualident<out qualident>
		[TypeArgumentList<out typeArguments, canBeUnbound>]
		(. typeRef = new InnerClassTypeReference(typeRef, qualident, typeArguments); .)
	}
.


NullableQuestionMark<ref TypeReference typeRef>
(. List<TypeReference> typeArguments = new List<TypeReference>(1); .)
=
	"?"
	(.
		if (typeRef != null) typeArguments.Add(typeRef);
		typeRef = new TypeReference("System.Nullable", typeArguments);
	.)
.

TypeArgumentList<out List<TypeReference> types, bool canBeUnbound>
(. 
	types = new List<TypeReference>();
	TypeReference type = null;
.)
=
	"<"
	( IF (canBeUnbound && (la.kind == Tokens.GreaterThan || la.kind == Tokens.Comma))
		(. types.Add(TypeReference.Null); .)
		{ "," (. types.Add(TypeReference.Null); .) }
	| Type<out type> (. types.Add(type); .)
	  { "," Type<out type> (. types.Add(type); .) }
	)
	">"
.

TypeParameterList<List<TemplateDefinition> templates>
(.
	AttributeSection section;
	List<AttributeSection> attributes = new List<AttributeSection>();
.)
=
	"<" { AttributeSection<out section> (. attributes.Add(section); .) }
	ident (. templates.Add(new TemplateDefinition(t.val, attributes)); .)
	{ "," { AttributeSection<out section> (. attributes.Add(section); .) }
	ident (. templates.Add(new TemplateDefinition(t.val, attributes)); .)}
	">"
.

TypeParameterConstraintsClause<List<TemplateDefinition> templates>
(. string name = ""; TypeReference type; .)
=
	ident                            (. if (t.val != "where") Error("where expected"); .)
	ident (. name = t.val; .)
	":"
	TypeParameterConstraintsClauseBase<out type> (. 
	                                                TemplateDefinition td = null;
	                                                foreach (TemplateDefinition d in templates) {
	                                                	if (d.Name == name) {
	                                                		td = d;
	                                                		break;
	                                                	}
	                                                }
	                                                if ( td != null) { td.Bases.Add(type); }
	                                             .)
	{ "," TypeParameterConstraintsClauseBase<out type> (.
	                                                    td = null;
	                                                    foreach (TemplateDefinition d in templates) {
	                                                    	if (d.Name == name) {
	                                                    		td = d;
	                                                    		break;
	                                                    	}
	                                                    }
	                                                    if ( td != null) { td.Bases.Add(type); }
	                                                   .) }
.

TypeParameterConstraintsClauseBase<out TypeReference type>
(. TypeReference t; type = null; .)
=
	"struct"          (. type = new TypeReference("struct"); .)
	| "class"         (. type = new TypeReference("struct"); .)
	| "new" "(" ")"   (. type = new TypeReference("struct"); .)
	| Type<out t>     (. type = t; .)
.

	
END CS.
