private ITypeMember parseFieldOrPropertyOrMethod(List<AnnotationSectionNode> annotations, EnumSet<Modifier> modifiers,
                bool partial, TypeReferenceNode type, int startPosition) {
            if (!isIdentifier(lexicalUnit)) {
                throw error(ParseErrorId.IdentifierExpected);
            }
            int sp = scanner.StartPosition;
            int len = getLexicalUnitLength();
            saveScannerState();
            var typeParameters = new ArrayList<SimpleNameTypeReferenceNode>();
            nextLexicalUnit(true);
            parseTypeParameters(typeParameters);
			Modifier setterAccess = checkSetterAccess();
			bool forceAsField = false;
			if (lexicalUnit == LexicalUnit.Multiply) {
				forceAsField = true;
                nextLexicalUnit(true);			
			}
            switch (lexicalUnit) {
            case OpenParenthesis:
				if (setterAccess != Modifier.Public || forceAsField) {
					throw error(ParseErrorId.IdentifierExpected);
				}
                var methodDeclaration = new MethodDeclarationNode { IsPartial = partial, ReturnType = type, NameOffset = sp, NameLength = len,
						StartPosition = startPosition };
                if (docCommentEndPosition > 0) {
                    methodDeclaration.DocumentationOffset = docCommentStartPosition;
                    methodDeclaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                    docCommentEndPosition = 0;
                }
                setSavedScannerState(methodDeclaration);
                methodDeclaration.Modifiers.addAll(modifiers);
                methodDeclaration.Annotations.addAll(annotations);
                foreach (var t in typeParameters) {
                    if (t.TypeReferenceKind != TypeReferenceKind.SimpleName || t.TypeArguments.size() > 0) {
                        throw error(ParseErrorId.SimpleNameExpected);
                    }
                    methodDeclaration.TypeParameters.add((SimpleNameTypeReferenceNode)t);
                }

                if (nextLexicalUnit(true) != LexicalUnit.CloseParenthesis) {
                    parseFormalParameters(methodDeclaration.Parameters, LexicalUnit.CloseParenthesis);
                } else {
                    nextLexicalUnit(true);
                }
                parseTypeParameterConstraintsClauses(methodDeclaration.ConstraintsClauses);
                switch (lexicalUnit) {
                case OpenBrace:
                    methodDeclaration.Body = parseBlockStatement();
					methodDeclaration.EndPosition = methodDeclaration.Body.EndPosition;
                    break;

                case SemiColon:
					methodDeclaration.EndPosition = scanner.EndPosition;
                    nextLexicalUnit(true);
                    break;

                default:
                    throw error(ParseErrorId.OpenBraceExpected);
                }
                return methodDeclaration;

            case OpenBrace:
				if (setterAccess != Modifier.Public || forceAsField) {
					throw error(ParseErrorId.IdentifierExpected);
				}
                var propertyDeclaration = new PropertyDeclarationNode { Type = type, NameOffset = sp, NameLength = len,
						StartPosition = startPosition };
                if (docCommentEndPosition > 0) {
                    propertyDeclaration.DocumentationOffset = docCommentStartPosition;
                    propertyDeclaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                    docCommentEndPosition = 0;
                }
                setSavedScannerState(propertyDeclaration);
                propertyDeclaration.Modifiers.addAll(modifiers);
                nextLexicalUnit(true);
                parseAccessorDeclaration(propertyDeclaration, false);
                if (lexicalUnit != LexicalUnit.CloseBrace) {
                    parseAccessorDeclaration(propertyDeclaration, false);
                }
                docCommentEndPosition = 0;
				propertyDeclaration.EndPosition = scanner.EndPosition;
                nextLexicalUnit(false);
                return propertyDeclaration;

            case Assign: {
				if (setterAccess != Modifier.Public || forceAsField) {
					throw error(ParseErrorId.IdentifierExpected);
				}
                var declaration = new FieldDeclarationNode { Type = type, StartPosition = startPosition };
                if (docCommentEndPosition > 0) {
                    declaration.DocumentationOffset = docCommentStartPosition;
                    declaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                    docCommentEndPosition = 0;
                }
                setSavedScannerState(declaration);
                declaration.Modifiers.addAll(modifiers);
                declaration.Annotations.addAll(annotations);
                nextLexicalUnit(true);
                var decl = new VariableDeclaratorNode { NameOffset = sp, NameLength = len };
                setSavedScannerState(decl);
                decl.Value = parseFieldInitializer();
                decl.EndPosition = decl.Value.EndPosition;
                declaration.Declarators.add(decl);
                while (lexicalUnit == LexicalUnit.Comma) {
                    if (!isIdentifier(nextLexicalUnit(true))) {
                        throw error(ParseErrorId.IdentifierExpected);
                    }
                    decl = new VariableDeclaratorNode { NameOffset = scanner.StartPosition, NameLength = getLexicalUnitLength() };
                    setScannerState(decl);
                    decl.EndPosition = scanner.EndPosition;
                    declaration.Declarators.add(decl);
                    if (nextLexicalUnit(true) == LexicalUnit.Assign) {
                        nextLexicalUnit(true);
                        decl.Value = parseFieldInitializer();
                        decl.EndPosition = decl.Value.EndPosition;
                    }
                }
                docCommentEndPosition = 0;
                declaration.EndPosition = parseSemiColon(false, false);
                return declaration;
            }

            case Comma: {
				if (setterAccess != Modifier.Public || forceAsField) {
					throw error(ParseErrorId.IdentifierExpected);
				}
                var declaration = new FieldDeclarationNode { Type = type, StartPosition = startPosition };
                if (docCommentEndPosition > 0) {
                    declaration.DocumentationOffset = docCommentStartPosition;
                    declaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                    docCommentEndPosition = 0;
                }
                setSavedScannerState(declaration);
                declaration.Modifiers.addAll(modifiers);
                declaration.Annotations.addAll(annotations);
                var decl = new VariableDeclaratorNode { NameOffset = sp, NameLength = len };
                setSavedScannerState(decl);
                decl.EndPosition = sp + len;
                declaration.Declarators.add(decl);
                do {
                    if (!isIdentifier(nextLexicalUnit(true))) {
                        throw error(ParseErrorId.IdentifierExpected);
                    }
                    decl = new VariableDeclaratorNode { NameOffset = scanner.StartPosition, NameLength = getLexicalUnitLength() };
                    setScannerState(decl);
                    declaration.Declarators.add(decl);
                    decl.EndPosition = scanner.EndPosition;
                    if (nextLexicalUnit(true) == LexicalUnit.Assign) {
                        nextLexicalUnit(true);
                        decl.Value = parseFieldInitializer();
                        decl.EndPosition = decl.Value.EndPosition;
                    }
                } while (lexicalUnit == LexicalUnit.Comma);
                docCommentEndPosition = 0;
                declaration.EndPosition = parseSemiColon(false, false);
                return declaration;
            }

            case SemiColon: {
				if ((modifiers.contains(Modifier.Public) || modifiers.contains(Modifier.Protected)) && !forceAsField) {
					var propertyShortDeclaration = new PropertyDeclarationNode { Type = type, NameOffset = sp, NameLength = len,
							StartPosition = startPosition };
					if (docCommentEndPosition > 0) {
						propertyShortDeclaration.DocumentationOffset = docCommentStartPosition;
						propertyShortDeclaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
						docCommentEndPosition = 0;
					}
					setSavedScannerState(propertyShortDeclaration);
					propertyShortDeclaration.Modifiers.addAll(modifiers);
					fakeParseShortProperty(propertyShortDeclaration, setterAccess, false);
					docCommentEndPosition = 0;
					propertyShortDeclaration.EndPosition = scanner.EndPosition;
					nextLexicalUnit(false);
					return propertyShortDeclaration;
				}
                var declaration = new FieldDeclarationNode { Type = type, StartPosition = startPosition };
                if (docCommentEndPosition > 0) {
                    declaration.DocumentationOffset = docCommentStartPosition;
                    declaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                    docCommentEndPosition = 0;
                }
                setSavedScannerState(declaration);
                declaration.Modifiers.addAll(modifiers);
                declaration.Annotations.addAll(annotations);
                var decl = new VariableDeclaratorNode { NameOffset = sp, NameLength = len };
                setSavedScannerState(decl);
                decl.EndPosition = sp + len;
                declaration.Declarators.add(decl);
                docCommentEndPosition = 0;
				declaration.EndPosition = scanner.EndPosition;
                nextLexicalUnit(false);
                return declaration;
            }

            default:
                throw error(ParseErrorId.UnexpectedLexicalUnit);
            }
        }
        private LocalDeclarationStatementNode parseLocalDeclarationStatement(TypeReferenceNode type, bool eatSemiColon) {
            var declaration = new LocalDeclarationStatementNode();
            setSavedScannerState(declaration);
            declaration.Type = type;
            var declarator = new VariableDeclaratorNode();
            setScannerState(declarator);
            declarator.NameOffset = scanner.StartPosition;
            declarator.NameLength = getLexicalUnitLength();
            declaration.Declarators.add(declarator);
            nextLexicalUnit(true);
            if (lexicalUnit == LexicalUnit.Assign) {
                nextLexicalUnit(true);
                declarator.Value = parseLocalVariableInitializer();
                declarator.EndPosition = declarator.Value.EndPosition;
            } else {
            	declarator.EndPosition = declarator.NameOffset + declarator.NameLength;
            }
            int endPosition = declarator.EndPosition;
            while (lexicalUnit == LexicalUnit.Comma) {
                if (!isIdentifier(nextLexicalUnit(true))) {
                    throw error(ParseErrorId.IdentifierExpected);
                }
                declarator = new VariableDeclaratorNode();
                setScannerState(declarator);
                declarator.NameOffset = scanner.StartPosition;
                declarator.NameLength = getLexicalUnitLength();
                declaration.Declarators.add(declarator);
                nextLexicalUnit(true);
                if (lexicalUnit == LexicalUnit.Assign) {
                    nextLexicalUnit(true);
                    declarator.Value = parseLocalVariableInitializer();
	                declarator.EndPosition = declarator.Value.EndPosition;
	            } else {
	            	declarator.EndPosition = declarator.NameOffset + declarator.NameLength;
                }
                endPosition = declarator.EndPosition;
            }
            if (eatSemiColon) {
                declaration.EndPosition = parseSemiColon(false, false);
            } else {
            	declaration.EndPosition = endPosition;
            }
            return declaration;
        }
		private String typeReferenceToString(TypeReferenceNode typeRef) {
			var sb = new StringBuilder();
			switch (typeRef.TypeReferenceKind) {
				case Int:
				case Long:
				case Short:
				case Float:
				case Double:
				case Boolean:
				case Byte:
				case Void:
				case String:
					sb.append(typeRef.TypeReferenceKind.toString().toLowerCase());
					break;

				case SimpleName:
					var simpleName = (SimpleNameTypeReferenceNode)typeRef;
					sb.append(new String(text, simpleName.NameOffset, simpleName.NameLength));
					if (simpleName.TypeArguments.size() > 0) {
						formatTypeArguments(simpleName.TypeArguments, sb);
					}
					break;

				case Qualified:
					var qtype = (QualifiedTypeReferenceNode)typeRef;
					sb.append(typeReferenceToString(qtype.EnclosingType));
					sb.append(".");
					sb.append(typeReferenceToString(qtype.SimpleName));
					break;

				case Array:
					var array = (ArrayTypeReferenceNode)typeRef;
					sb.append(typeReferenceToString(array.ElementType));
					sb.append("[]");
					break;

				default:
					throw new RuntimeException("Unhandled type kind: " + typeRef.TypeReferenceKind);
			}
			return sb.toString();
		}
        private IndexerDeclarationNode parseIndexerDeclaration(List<AnnotationSectionNode> annotations, EnumSet<Modifier> modifiers,
                bool partial, TypeReferenceNode type, bool inInterface, int startPosition) {
            var declaration = new IndexerDeclarationNode { Type = type, StartPosition = startPosition };
            if (docCommentEndPosition > 0) {
                declaration.DocumentationOffset = docCommentStartPosition;
                declaration.DocumentationLength = docCommentEndPosition - docCommentStartPosition;
                docCommentEndPosition = 0;
            }
            setSavedScannerState(declaration);
            declaration.Modifiers.addAll(modifiers);
            declaration.Annotations.addAll(annotations);
            if (lexicalUnit != LexicalUnit.OpenBracket) {
                throw error(ParseErrorId.OpenBracketExpected);
            }
            if (nextLexicalUnit(true) != LexicalUnit.CloseBracket) {
                parseFormalParameters(declaration.Parameters, LexicalUnit.CloseBracket);
            } else {
                nextLexicalUnit(true);
            }
			Modifier setterAccess = Modifier.Public;
			if (lexicalUnit == LexicalUnit.Xor) {
				if (!inInterface) {
					throw error(ParseErrorId.OpenBraceExpected);
				}
				setterAccess = Modifier.Private;
                nextLexicalUnit(true);			
			}
			if (lexicalUnit == LexicalUnit.SemiColon) {
				if (!inInterface) {
					throw error(ParseErrorId.OpenBraceExpected);
				}
				fakeParseShortProperty(declaration, setterAccess, inInterface);
				docCommentEndPosition = 0;
				declaration.EndPosition = scanner.EndPosition;
				nextLexicalUnit(false);
				return declaration;
			}
            if (lexicalUnit != LexicalUnit.OpenBrace) {
                throw error(ParseErrorId.OpenBraceExpected);
            }
            nextLexicalUnit(true);
            parseAccessorDeclaration(declaration, inInterface);
            if (lexicalUnit != LexicalUnit.CloseBrace) {
                parseAccessorDeclaration(declaration, inInterface);
            }
            docCommentEndPosition = 0;
			declaration.EndPosition = scanner.EndPosition;
            nextLexicalUnit(false);
            return declaration;
        }
		private void print(TypeReferenceNode typeReference, StringBuilder sb) {
			switch (typeReference.TypeReferenceKind) {
			case Int:
			case Char:
			case Long:
			case Short:
			case Float:
			case Double:
			case Boolean:
			case Byte:
			case Void:
			case String:
				sb.append(typeReference.TypeReferenceKind.toString().toLowerCase());
				break;

			case SimpleName:
				var simpleName = (SimpleNameTypeReferenceNode)typeReference;
				sb.append(new String(text, simpleName.NameOffset, simpleName.NameLength));
				if (simpleName.TypeArguments.size() > 0) {
					print(simpleName.TypeArguments, sb);
				}
				break;

			case Qualified:
				var qtype = (QualifiedTypeReferenceNode)typeReference;
				print(qtype.EnclosingType, sb);
				sb.append(".");
				print(qtype.SimpleName, sb);
				break;

			case Array:
				var array = (ArrayTypeReferenceNode)typeReference;
				print(array.ElementType, sb);
				sb.append("[]");
				break;

			case Wildcard:
				sb.append("?");
				break;
				
			case LowerBoundedWildcard:
				var wildcard = (WildcardTypeReferenceNode)typeReference;
				print(wildcard.Bound, sb);
				sb.append(" : ?");
				break;
				
			case UpperBoundedWildcard:
				wildcard = (WildcardTypeReferenceNode)typeReference;
				sb.append("? : ");
				print(wildcard.Bound, sb);
				break;
				
			default:
				throw new RuntimeException("Unhandled type kind: " + typeReference.TypeReferenceKind);
			}
		}