EXTERNPROTO ParseExternProto(out string nodeTypeId)
        {
            // EXTERNPROTO nodeTypeId [ externInterfaceDeclarations ] URLList

            string tokenEXTERNPROTO = GetNextIDToken();

            if (tokenEXTERNPROTO != "EXTERNPROTO")
            {
                ErrorParsingToken("EXTERNPROTO", tokenEXTERNPROTO, "EXTERNPROTO statement");
            }

            nodeTypeId = GetNextIDToken();

            char ts = GetNextTerminalSymbolToken();

            if (ts != '[')
            {
                ErrorParsingToken("[", ts.ToString(), "EXTERNPROTO statement");
            }

            List <InterfaceDeclaration> interfaceDeclarations = ParseExternInterfaceDeclarations();

            ts = GetNextTerminalSymbolToken();
            if (ts != ']')
            {
                ErrorParsingToken("]", ts.ToString(), "EXTERNPROTO statement");
            }

            EXTERNPROTO ret = new EXTERNPROTO();

            ret.InterfaceDeclarations = interfaceDeclarations;
            ret.ProtoNodeName         = nodeTypeId;
            ret.URLList = ParseSFStringOrMFStringValue();
            return(ret);
        }
		X3DNode ParseNode(string DEFName)
		{
			// nodeTypeId { nodeBody } | Script { scriptBody }

			string nodeTypeId=GetNextIDToken();

			char ts=GetNextTerminalSymbolToken();
			if(ts!='{') ErrorParsingToken("{", ts.ToString(), "node statement '"+nodeTypeId+"'");

			X3DNode node=GetNodeByName(nodeTypeId);

			bool returnNull=false;
			if(node is IDummyNode)
			{
				switch(errorHandling.DummyNode)
				{
					case DummyNodeHandling.Error:
						ErrorParsing(VRMLReaderError.UnexpectedNodeType, nodeTypeId);
						break;
					case DummyNodeHandling.Warn:
						WriteWarning("Warning: Non-standard node found: '"+nodeTypeId+"' that can and will be parsed in line: "+line);
						break;
					case DummyNodeHandling.Ignore:
						returnNull=true;
						break;
				}
			}

			if(node==null)
			{
				switch(errorHandling.UnknownNode)
				{
					case UnknownNodeHandling.ErrorUnknownNodes:
						ErrorParsing(VRMLReaderError.UnexpectedNodeType, nodeTypeId);
						break;
					case UnknownNodeHandling.WarnUnknownNodes:
						WriteWarning("Warning: Unknown node found: '"+nodeTypeId+"' in line: "+line);
						returnNull=true;
						break;
					case UnknownNodeHandling.ParseAsExternProtoWarn:
						WriteWarning("Warning: Unknown node found: '"+nodeTypeId+"', will be parsed as EXTRENPROTO in line: "+line);
						break;
					case UnknownNodeHandling.IgnoreUnknownNodes:
						returnNull=true;
						break;
				}

				EXTERNPROTO externProto=new EXTERNPROTO();
				externProto.ProtoNodeName=nodeTypeId;
				node=externProto;
			}

			if(DEFName!=null)
			{
				instances[DEFName]=node;
				node.NameDEF=DEFName;
			}

			if(node is IScriptNode) ParseScriptBody(node);
			else ParseNodeBody(node);

			ts=GetNextTerminalSymbolToken();
			if(ts!='}') ErrorParsingToken("}", ts.ToString(), "node statement '"+nodeTypeId+"'");

			return returnNull?null:node;
		}
		EXTERNPROTO ParseExternProto(out string nodeTypeId)
		{
			// EXTERNPROTO nodeTypeId [ externInterfaceDeclarations ] URLList

			string tokenEXTERNPROTO=GetNextIDToken();
			if(tokenEXTERNPROTO!="EXTERNPROTO") ErrorParsingToken("EXTERNPROTO", tokenEXTERNPROTO, "EXTERNPROTO statement");

			nodeTypeId=GetNextIDToken();

			char ts=GetNextTerminalSymbolToken();
			if(ts!='[') ErrorParsingToken("[", ts.ToString(), "EXTERNPROTO statement");

			List<InterfaceDeclaration> interfaceDeclarations=ParseExternInterfaceDeclarations();

			ts=GetNextTerminalSymbolToken();
			if(ts!=']') ErrorParsingToken("]", ts.ToString(), "EXTERNPROTO statement");

			EXTERNPROTO ret=new EXTERNPROTO();
			ret.InterfaceDeclarations=interfaceDeclarations;
			ret.ProtoNodeName=nodeTypeId;
			ret.URLList=ParseSFStringOrMFStringValue();
			return ret;
		}